Come rimuovere lestensione del nome di file da un elenco di nomi di file in bash

Sto cercando di rimuovere lestensione del nome di file da un elenco di file che ho generato con quanto segue bash script:

 #!/bin/bash file_list=$(find . -type f) #assuming that the files are stored in the same directory trimmed_file_list=$(printf "%s\n" "${file_list[@]%.*}") printf "%s\n" "${trimmed_file_list[@]}" 

Questa espansione ritaglia lestensione dalla ultima voce dellelenco, ma non da quelle precedenti.

Ad esempio, desidero il seguente elenco:

 file1.pdf file2.pdf file3.png 

Per diventare

 file1 file2 file3 

Ma invece ottengo:

 file1.pdf file2.pdf file3 

Preferirei non farlo in un ciclo, mi piacerebbe usare lespansione dei parametri. Voglio evitare il taglio perché desidero rimuovere solo lultima estensione nel file.

Ci sono un buon numero di argomenti sullespansione dei parametri e sembra che bash potrebbe soffocare su find” uso di newline … Non sono proprio sicuro. Se un altro degli argomenti preesistenti spiega questo problema, non capisco completamente cosa sta succedendo.

Argomenti che sembrano correlato ma non sembra risolvere il mio problema:

Commenti

  • Il tuo titolo menziona gli array, ma non cè nessun array nel tuo codice.
  • @Kusalananda Grazie! ‘ me ne sono reso conto da quando lho chiesto. Sto ancora imparando 🙂
  • @Kusalananda I ‘ sono andato avanti e ho modificato la domanda in modo che corrispondesse maggiormente al problema. Ciò dovrebbe impedire che ricerche errate su Google raggiungano la pagina. Grazie per le informazioni!

Risposta

Potresti fare tutto in un comando.

find /path/to -type f -execdir bash -c "printf "%s\n" "${@%.*}"" bash {} + 

Commenti

  • Grazie! In realtà ho bisogno di creare un paio di copie dellarray, una per un menu che ha il nome del file modificato e una che manterrà il valore di indice originale in modo da poter chiamare il file dal menu. È davvero sorprendente quanto bash possa fare però! La capacità di incorporare tutto in un unico comando continua a stupirmi! : D

Risposta

Credo che tu voglia creare un array invece di una stringa:

IFS=$"\n" # split on newline only set -o noglob # disable the glob part file_list=($(find . -name "*.*" -type f)) 

O con bash 4.4+, senza interruzioni nei percorsi dei file con caratteri di nuova riga:

readarray -td "" file_list < <(find . -name "*.*" -type f -print0) 

Quindi lespansione del tuo parametro dovrebbe funzionare, anche se qui avrebbe più senso usare di nuovo una variabile array:

trimmed_file_list=("${file_list[@]%.*}") 

Nel tuo esempio di codice, stai creando una stringa quindi chiedendo lespansione del parametro per rimuovere tutto ciò che è dopo il carattere punto finale nella stringa completa.

Commenti

  • Grazie! Lo proverò non appena raggiungo la mia scrivania la mattina.
  • Questo presume che nessun nome di file in quella directory contenga spazi bianchi o caratteri globbing.
  • @Wildcard, dovrebbe essere risolto dallultima modifica.
  • @Wildcard Grazie per il puntatore! ‘ sto generando i file che vengono rilasciati in questa directory a livello di programmazione, quindi ‘ non dovrebbe essere un problema.

Risposta

Il tuo codice non include alcun array. Inoltre, inserisce un elenco di nomi di file in una stringa, $file_list. Il contenuto della stringa terminerà con file3.png e la sostituzione del parametro rimuove .png dalla stringa, lasciandoti con una singola stringa di nomi di file dove lultimo nome di file non ha un suffisso per il nome di file.

Linserimento di più oggetti separati (nomi di percorso) in una singola stringa impedisce automaticamente allo script di funzionare correttamente per i file i cui nomi contengono spazi (o qualsiasi delimitatore utilizzato dalla stringa). Luso di un array non sarebbe di aiuto in quanto suddivideresti comunque loutput di find sugli spazi vuoti.


Per tagliare lestensione di tutti i nomi di file dei file normali nella o sotto la directory corrente:

find . -type f -name "*.*" -exec sh -c " for pathname do printf "Would move %s to %s...\n" "$pathname" "${pathname%.*}" # mv -i "$pathname" "${pathname%.*}" done" sh {} + 

Cerca file regolari i cui nomi contengono almeno un punto. I nomi di percorso di questi file vengono inseriti in batch in un piccolo script di shell che scorre su di essi. Lo script della shell rinomina i file rimuovendo lultimo punto nel nome del file e tutto ciò che viene dopo. Lattuale comando mv è commentato per motivi di sicurezza.

Il comando find funge da generatore di nomi di percorso per il script di shell interno e abbiamo la garanzia di elaborare correttamente i nomi di percorso contenenti spazi, nuove righe e tabulazioni. Non è necessario memorizzare loutput dei comandi nelle variabili.

Se si dispone di un array di nomi di percorso, possibilmente creati utilizzando

shopt -s globstar nullglob file_list=( **/*.* ) # get pathnames of files with dots in their names 

Allora si sarebbe in grado di visualizzare i nomi di percorso senza suffissi con

printf "%s\n" "${file_list[@]%.*}" 

Se questo potrebbe aiutarti, non lo so. Se vuoi usare i nomi di percorso senza suffissi per qualcosa , quindi utilizzare loutput del comando printf sopra sarebbe la cosa sbagliata da fare (torneresti a non gestire più uno strano percorso). e il modo in cui elimini i suffissi del nome del file dipende da cosa vorresti fare con il risultato.

Correlati:

Commenti

  • Grazie! La tua maestria nel bash è molto evidente! ‘ sto ancora raschiando la superficie … Grazie per aver dedicato del tempo per aiutare 🙂

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *