Come ottenere solo il nome file usando sed


17

Come posso ottenere solo il nome file usando sed? Ho questo

out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")

Ma ottengo anche il percorso /root/video.mp4e voglio solo video.mp4.

Risposte:


26

basenamedai coreutils GNU può aiutarti a fare questo lavoro:

$ basename /root/video.mp4
video.mp4

Se conosci già l'estensione del file, puoi richiamare basenameusando la sintassi basename NAME [SUFFIX]per rimuoverlo:

$ basename /root/video.mp4 .mp4
video

Oppure un'altra opzione sarebbe tagliare tutto dopo l'ultimo punto usando sed:

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old

3
Usando sed 's/\.[^.]*$//'come hai, fallirà per (nascosto) .filenamee .per le ..directory
Peter.O

9

La soluzione più semplice è rimuovere tutto fino all'ultima comparsa di /:

echo /root/video.mp4 | sed 's/.*\///'


5

Utilizzare uno dei seguenti modi:

out_file="${in_file##*/}"

out_file="$(basename $in_file)"

out_file="$(echo $in_file | sed 's=.*/==')"

out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"

ps. Ottieni la stessa stringa perché nell'istruzione \(.*\.\)corrisponde alla stringa dall'inizio fino al punto ( /root/video.) e quindi aggiungi manualmente .mp4quale è la stessa della stringa originale. Dovresti usare s=.*\([^/]*\)=\1=invece.

Aggiornamento: (il primo è stato risolto ora)

Per ottenere l'unico nome file senza estensione puoi:

out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"

out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"

out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'

Ma con uno di questi metodi ottengo il nome file con il formato e ho bisogno di ottenere solo il nome file e inserire manualmente un nuovo formato.
Shixons,

Ah, ha senso. Ho aggiornato la mia risposta.
corsa il

@rush: ci saranno casi limite, ad es. per un file chiamato my.file.tar.gz.
donothings successo

@donothings c'era un simbolo punto mancante nell'ultimo sede awk. Fisso. Grazie.
precipita il

4

Uno dei fondamenti dell'uso di regex è che i modelli sono avidi per natura quando si specifica il jolly. Mentre la risposta proposta da @uloBasEI è sicuramente una risposta funzionante, richiede anche l'uso del comando basename. La domanda originale di @Shixons richiede una soluzione usando solo sed.

Prima di continuare, è sempre utile sapere quale versione di sed è l'obiettivo. Sto assumendo BSD (come fornito con OSX).

Prima di tutto, il modello proposto nella domanda originale non funziona perché cattura tutto dall'inizio della stringa di input fino all'ultimo punto incluso. Senza ancore, questa ricerca inghiottirà tutto da sinistra a destra. Il modello corrispondente "/ 1", quindi, è tutto fino all'ultimo punto incluso. Anche un nome di file con più punti verrà inghiottito intero. Non è il risultato desiderato affatto.

Il primo passo è stabilire una strategia per identificare i modelli. Qui, ti piacerebbe sbarazzarti di tutto a sinistra del nome del file (ci occuperemo dell'estensione in seguito):

out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"

La ricerca corrisponde dall'inizio della stringa. Abbina uno schema di "/.*" zero o più volte ed elimina tutto in seguito. Stampiamo i motivi abbinati con "\ 1". Non stiamo cercando a livello globale; stiamo cercando dall'inizio della stringa specificando l'ancora ^.

Otteniamo maggiore chiarezza abilitando l'opzione "-E" in modo da non dover sfuggire alle parentesi:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"

Quindi ora abbiamo la parte a sinistra. Aggiungiamo la parte a destra. Nota che dobbiamo mantenere la parte sinistra come modello perché è così che possiamo specificare che appare zero o più volte. Tutto ciò che facciamo ora è aggiungere un modello per la parte a destra:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"

Stampiamo solo la seconda corrispondenza, scartando così tutto tranne il nome file. Ma dobbiamo ancora rimuovere l'estensione del nome file.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"

"$" Alla fine è facoltativo.

Infine, per aggiungere la nuova estensione basta rivedere in questo modo:

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"

Un'ulteriore ottimizzazione è rendere facoltativa la prima barra diretta per gestire i percorsi relativi:

out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"

Mi sono imbattuto in questa domanda essendo pigro mentre cercavo un modello sed per sostituire il nome di base . Sto lavorando su un sistema privato che non ha quel comando installato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.