GNU/Linux >> Tutoriels Linux >  >> Linux

Bash :Utilisation procédurale sécurisée des espaces blancs de la recherche dans la sélection ?

Étant donné ces noms de fichiers :

$ ls -1
file
file name
otherfile

bash lui-même fonctionne parfaitement avec les espaces blancs intégrés :

$ 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
#?

Cependant, parfois je ne veux pas travailler avec tous les fichiers, ou même strictement dans $PWD , où find entre. Qui gère également les espaces blancs :

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

J'essaie de concocter une version whispace-safe de ce scriptlet qui prendra la sortie de find et présentez-le dans select :

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

Cependant, cela explose avec des espaces dans les noms de fichiers :

$ 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

Normalement, je contournerais ce problème en jouant avec IFS . Cependant :

$ 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'

Quelle est la solution à cela ?

Réponse acceptée :

Si vous n'avez besoin que de gérer les espaces et les tabulations (et non les sauts de ligne intégrés), vous pouvez utiliser mapfile (ou son synonyme, readarray ) pour lire dans un tableau, par ex. donné

$ ls -1
file
other file
somefile

alors

$ 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

Si vous faites besoin de gérer les nouvelles lignes et votre bash version fournit un mapfile délimité par des valeurs nulles , vous pouvez alors le modifier en IFS= mapfile -t -d '' files < <(find . -type f -print0) . Sinon, assemblez un tableau équivalent à partir de find délimité par null sortie à l'aide d'un read boucle :

$ 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

le -d l'option a été ajoutée au mapfile dans bash version 4.4 irc

En relation:acing -Find Meaning- Recherche de dictionnaire !
Linux
  1. La fête ?

  2. Comment enregistrer chaque commande tapée dans bash et chaque opération de fichier ?

  3. Trouver le fichier journal de Firefox ?

  4. Comment trier les fichiers dans des dossiers par type de fichier sur bash (avec la commande 'file') ?

  5. bash trouver des répertoires

Bash :ajouter au fichier

Comment utiliser les opérateurs de test de fichiers Bash sous Linux

35 exemples de scripts bash

Comment rechercher des fichiers avec des dizaines de critères avec la commande Bash Find

Comment faire écho dans le fichier

Comment utiliser Sed pour rechercher et remplacer une chaîne dans un fichier