GNU/Linux >> Linux Esercitazione >  >> Linux

Bash:uso procedurale sicuro per gli spazi bianchi di Trova nella selezione?

Dati questi nomi di file:

$ ls -1
file
file name
otherfile

bash di per sé funziona perfettamente con gli spazi bianchi incorporati:

$ for file in *; do echo "$file"; done
file
file name
otherfile
$ select file in *; do echo "$file"; done
1) file
2) file name
3) otherfile
#?

Tuttavia, a volte potrei non voler lavorare con tutti i file, o anche rigorosamente in $PWD , che è dove find entra. Che gestisce anche lo spazio bianco nominalmente:

$ find -type f -name file*
./file
./file name
./directory/file
./directory/file name

Sto cercando di inventare una versione whispace-safe di questo scriptlet che prenderà l'output di find e presentalo in select :

$ select file in $(find -type f -name file); do echo $file; break; done
1) ./file
2) ./directory/file

Tuttavia, questo esplode con uno spazio bianco nei nomi dei file:

$ select file in $(find -type f -name file*); do echo $file; break; done
1) ./file        3) name          5) ./directory/file
2) ./file        4) ./directory/file  6) name

Di solito, aggiravo questo problema scherzando con IFS . Tuttavia:

$ IFS=$'n' select file in $(find -type f -name file*); do echo $file; break; done
-bash: syntax error near unexpected token `do'
$ IFS='n' select file in $(find -type f -name file*); do echo $file; break; done
-bash: syntax error near unexpected token `do'

Qual è la soluzione a questo?

Risposta accettata:

Se hai solo bisogno di gestire spazi e tabulazioni (non le nuove righe incorporate), puoi usare mapfile (o il suo sinonimo, readarray ) per leggere in un array, ad es. dato

$ ls -1
file
other file
somefile

poi

$ IFS= mapfile -t files < <(find . -type f)
$ select f in "${files[@]}"; do ls "$f"; break; done
1) ./file
2) ./somefile
3) ./other file
#? 3
./other file

Se fai devi gestire le nuove righe e il tuo bash version fornisce un mapfile delimitato da null , quindi puoi modificarlo in IFS= mapfile -t -d '' files < <(find . -type f -print0) . Altrimenti, assembla un array equivalente da find delimitato da null output usando una read ciclo:

$ touch $'filenamenwithnnewlines'
$ 
$ files=()
$ while IFS= read -r -d '' f; do files+=("$f"); done < <(find . -type f -print0)
$ 
$ select f in "${files[@]}"; do ls "$f"; break; done
1) ./file
2) ./somefile
3) ./other file
4) ./filename
with
newlines
#? 4
./filename?with?newlines

il -d l'opzione è stata aggiunta a mapfile in bash versione 4.4 iirc

Correlati:acing -Trova significato- Cerca nel dizionario!
Linux
  1. Come usare i comandi della cronologia di Bash

  2. Trova il file di registro di Firefox?

  3. Quale metodo utilizza Unzip per trovare un singolo file in un archivio?

  4. Funzione Bash per trovare il modello di corrispondenza dei file più recente

  5. Modifica ricorsivamente le estensioni dei file in Bash

Bash:aggiungi al file

Come utilizzare gli operatori di test di file Bash in Linux

35 Esempi di script Bash

Come trovare file con dozzine di criteri con il comando Trova Bash

Come fare eco in un file

Come utilizzare Sed per trovare e sostituire una stringa in un file