2010-07-29 17 views

risposta

461

maggior parte UNIX-like hanno un eseguibile basename per uno scopo molto simile (e dirname per il percorso):

pax> a=/tmp/file.txt 
pax> b=$(basename $a) 
pax> echo $b 
file.txt 

che purtroppo appena ti dà il nome del file, tra cui l'estensione, così avresti bisogno di trovare un modo per mettere a nudo che fuori pure.

Quindi, dato che si deve fare comunque, si può anche trovare un metodo che può rimuovere il percorso e l'estensione.

Un modo per farlo (e questa è una soluzione -solo bash, che necessitano di nessun altro eseguibili):

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

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

Quel piccolo frammento di imposta xpath (il percorso del file), xpref (il prefisso del file, cosa lo stavi chiedendo specificamente) e xfext (l'estensione del file).

+0

So che c'è qualcosa a che fare con bash come sopra. Semplicemente non so quale sia la parola chiave. Vorrei ottenere ottenere il percorso, il nome file e l'estensione separati in variabili diverse. – Keith

+0

Se si desidera utilizzare il percorso: percorso = $ (echo $ nomefile | sed -e 's/\/[^ \ /] * $/\ //') Se si desidera ottenere l'estensione: ext = $ (echo $ nomefile | sed -e 's /[^\.]*\.//') – jcubic

+3

@Keith: per il percorso, usare 'percorso = $ (nomefile $ nomefile)'; non c'è un comando per darti l'estensione di per sé, ma @paxdiablo ti ha mostrato come la shell può farlo. –

10
$ source_file_filename_no_ext=${source_file%.*} 
$ echo ${source_file_filename_no_ext##*/} 
+0

Ho solo un carattere jolly con l'estensione usando questo. – Kebman

18

Ecco un modo semplice per ottenere il nome del file da un percorso:

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

Per rimuovere l'estensione è possibile utilizzare, assumendo il nome di file ha un solo punto (il punto di estensione):

cut -d"." -f1 
+7

Questo non è un buon presupposto, e ci sono strumenti e comandi specificamente progettati per farlo correttamente. – Tony

+0

Inoltre, non raccomanderei l'uso del nome variabile 'PATH', poiché questo può essere in conflitto con la variabile' PATH' del sistema – Tabea

19

basename e dirname soluzioni sono più convenienti. Questi sono i comandi alternativi:

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

Ciò restituisce test.old.img come basename.

Questo è il sale nome del file senza estensione:

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

Riporta test.old.

E la seguente istruzione fornisce il percorso completo come il comando dirname.

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

Riporta /opt/datastores/sda2

+0

cool, e se ci fossero parametri? –

6

Alcune opzioni più alternative perché regex (REGI?) Sono impressionanti!

Ecco una regex semplice per fare il lavoro:

regex="[^/]*$" 

Esempio (grep):

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

Esempio (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 

Se è necessaria un'espressione regolare più complessa: Ad esempio, il percorso è racchiuso in una stringa.

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 

soluzione totale con espressioni regolari:

Questa funzione può dare il nome del file, con o senza l'estensione di un percorso file Linux, anche se il nome del file ha molteplici s in esso "". Può anche gestire spazi nel percorso file e se il percorso del file è incorporato o avvolto in una stringa.

#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" 

Se hai a pasticciare con un percorso di Windows si può iniziare con questo:

[^\\]*$  
5
$ file=${$(basename $file_path)%.*} 
+0

Restituisce "sostituzione errata" in bash v4.4.7. Penso che la soluzione sed di Fırat KÜÇÜK sia migliore, cioè $ (basename $ the_file_path) | sed "s /\..*//" – Marshal

+0

Intendevo 'echo $ (basename $ the_file_path) | sed "s /\..*//" ' – Marshal

Problemi correlati