483 Stimmen

Nur den Dateinamen aus einem Pfad in einem Bash-Skript abrufen

Wie erhalte ich nur den Dateinamen ohne die Erweiterung und ohne Pfad?

Mit der folgenden Option erhalte ich keine Erweiterung, aber ich habe den Pfad trotzdem angehängt:

source_file_filename_no_ext=${source_file%.*}

822voto

paxdiablo Punkte 809679

Viele UNIX-ähnliche Betriebssysteme haben eine basename für einen sehr ähnlichen Zweck ausgeführt werden kann (und dirname für den Pfad):

pax> full_name=/tmp/file.txt
pax> base_name=$(basename ${full_name})
pax> echo ${base_name}
file.txt

Damit erhalten Sie leider nur den Dateinamen, einschließlich die Verlängerung, also müssen Sie einen Weg finden, diese auch zu entfernen.

Da Sie das also sowieso tun müssen, können Sie auch eine Methode finden, die den Pfad entfernt y die Verlängerung.

Eine Möglichkeit, dies zu tun (und dies ist eine bash -Lösung, die keine weiteren ausführbaren Dateien benötigt):

pax> full_name=/tmp/xx/file.tar.gz
pax> xpath=${full_name%/*} 
pax> xbase=${full_name##*/}
pax> xfext=${xbase##*.}
pax> xpref=${xbase%.*}
pax> echo "path='${xpath}', pref='${xpref}', ext='${xfext}'"

path='/tmp/xx', pref='file.tar', ext='gz'

Dieser kleine Schnipsel setzt xpath (der Dateipfad), xpref (das Dateipräfix, nach dem Sie ausdrücklich gefragt haben) und xfext (die Dateierweiterung).

87voto

Fırat KÜÇÜK Punkte 5138

basename y dirname Lösungen sind bequemer. Das sind alternative Befehle:

FILE_PATH="/opt/datastores/sda2/test.old.img"
echo "$FILE_PATH" | sed "s/.*\///"

Dies ergibt test.old.img wie basename .

Dies ist der Dateiname des Salzes ohne Erweiterung:

echo "$FILE_PATH" | sed -r "s/.+\/(.+)\..+/\1/"

Sie gibt zurück test.old .

Und die folgende Anweisung gibt den vollständigen Pfad an dirname Befehl.

echo "$FILE_PATH" | sed -r "s/(.+)\/.+/\1/"

Sie gibt zurück /opt/datastores/sda2

27voto

Ivry345 Punkte 285

Hier ist eine einfache Methode, um den Dateinamen aus einem Pfad zu ermitteln:

echo "$PATH" | rev | cut -d"/" -f1 | rev

Um die Erweiterung zu entfernen, können Sie, vorausgesetzt der Dateiname hat nur EINEN Punkt (den Erweiterungspunkt), verwenden:

cut -d"." -f1

22voto

mihai Punkte 4309
$ file=${$(basename $file_path)%.*}

16voto

jkdba Punkte 2053

Einige weitere alternative Optionen, denn Regexe (regi ?) sind genial!

Hier ist eine einfache Regex, die diese Aufgabe erfüllt:

 regex="[^/]*$"

Beispiel (grep):

 FP="/hello/world/my/file/path/hello_my_filename.log"
 echo $FP | grep -oP "$regex"
 #Or using standard input
 grep -oP "$regex" <<< $FP

Beispiel (awk):

 echo $FP | awk '{match($1, "$regex",a)}END{print a[0]}
 #Or using stardard input
 awk '{match($1, "$regex",a)}END{print a[0]} <<< $FP

Wenn Sie eine kompliziertere Regex benötigen: Zum Beispiel ist Ihr Pfad in eine Zeichenkette verpackt.

 StrFP="my string is awesome file: /hello/world/my/file/path/hello_my_filename.log sweet path bro."

 #this regex matches a string not containing / and ends with a period 
 #then at least one word character 
 #so its useful if you have an extension

 regex="[^/]*\.\w{1,}"

 #usage
 grep -oP "$regex" <<< $StrFP

 #alternatively you can get a little more complicated and use lookarounds
 #this regex matches a part of a string that starts with /  that does not contain a / 
 ##then uses the lazy operator ? to match any character at any amount (as little as possible hence the lazy)
 ##that is followed by a space
 ##this allows use to match just a file name in a string with a file path if it has an exntension or not
 ##also if the path doesnt have file it will match the last directory in the file path 
 ##however this will break if the file path has a space in it.

 regex="(?<=/)[^/]*?(?=\s)"

 #to fix the above problem you can use sed to remove spaces from the file path only
 ## as a side note unfortunately sed has limited regex capibility and it must be written out in long hand.
 NewStrFP=$(echo $StrFP | sed 's:\(/[a-z]*\)\( \)\([a-z]*/\):\1\3:g')
 grep -oP "$regex" <<< $NewStrFP

Komplettlösung mit Regexen:

Diese Funktion kann Ihnen den Dateinamen mit oder ohne Erweiterung eines Linux-Dateipfades liefern, auch wenn der Dateiname mehrere ". "s enthält. Sie kann auch mit Leerzeichen im Dateipfad umgehen und wenn der Dateipfad eingebettet oder in eine Zeichenkette eingeschlossen ist.

#you may notice that the sed replace has gotten really crazy looking
#I just added all of the allowed characters in a linux file path
function Get-FileName(){
    local FileString="$1"
    local NoExtension="$2"
    local FileString=$(echo $FileString | sed 's:\(/[a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*\)\( \)\([a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*/\):\1\3:g')

    local regex="(?<=/)[^/]*?(?=\s)"

    local FileName=$(echo $FileString | grep -oP "$regex")

    if [[ "$NoExtension" != "" ]]; then
        sed 's:\.[^\.]*$::g' <<< $FileName
    else
        echo "$FileName"
    fi
}

## call the function with extension
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro."

##call function without extension
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." "1"

Wenn Sie mit einem Windows-Pfad herumspielen müssen, können Sie mit diesem beginnen:

 [^\\]*$

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X