web-dev-qa-db-fra.com

Comment séparer la sortie de commande sur des lignes individuelles

list=`ls -a R*`
echo $list

Dans un script Shell, cette commande echo répertorie tous les fichiers du répertoire en cours commençant par R, mais sur une ligne. Comment puis-je imprimer chaque article sur une ligne?

J'ai besoin d'une commande générique pour tous les scénarios se produisant avec ls, du, find -type -d, etc.

8
Anony

Si la sortie de la commande contient plusieurs lignes, citez vos variables pour conserver ces nouvelles lignes lors de l'écho:

echo "$list"

Sinon, le Shell développera et divisera le contenu de la variable sur des espaces (espaces, nouvelles lignes, onglets) et ceux-ci seront perdus.

9
muru

Au lieu de mettre à tort la sortie de ls dans une variable, puis de echoing, qui supprime toutes les couleurs, utilisez

ls -a1

De man ls

       -1     list one file per line.  Avoid '\n' with -q or -b

Je ne vous conseille rien de faire avec la sortie de ls, sauf l'afficher :)

Utilisez par exemple Shell globs et une boucle for pour créer quelque chose avec les fichiers ...

shopt -s dotglob                  # to include hidden files*

for i in R/*; do echo "$i"; done

* ceci n'inclut pas le répertoire actuel . ni son parent .. si

14
Zanna

Tout en le mettant entre guillemets sous la forme @muru suggéré fera effectivement ce que vous avez demandé, vous pouvez également envisager d'utiliser un tableau pour cela. Par exemple:

IFS=$'\n' dirs=( $(find . -type d) )

Le IFS=$'\n' indique à bash de ne scinder que la sortie sur les caractères de nouvelle ligne pour obtenir chaque élément du tableau. Sans lui, il se divisera en espaces, donc a file name with spaces.txt serait composé de 5 éléments distincts au lieu d'un. Cette approche sera interrompue si vos noms de fichier/répertoire peuvent contenir des nouvelles lignes (\n). Cela enregistrera chaque ligne de la sortie de la commande en tant qu'élément du tableau.

Notez que j'ai également changé l'ancien style `command` en $(command), qui est la syntaxe préférée.

Vous avez maintenant un tableau appelé $dirs, chaque bof dont les éléments est une ligne de la sortie de la commande précédente. Par exemple:

$ find . -type d
.
./olad
./ho
./ha
./ads
./bar
./ga
./da
$ IFS=$'\n' dirs=( $(find . -type d) )
$ for d in "${dirs[@]}"; do
    echo "DIR: $d"
  done
DIR: .
DIR: ./olad
DIR: ./ho
DIR: ./ha
DIR: ./ads
DIR: ./bar
DIR: ./ga
DIR: ./da

Maintenant, à cause d'une certaine étrangeté bash (voir here ), vous devrez réinitialiser IFS à la valeur d'origine après avoir effectué cette opération. Alors, sauvegardez-le et modifiez-le:

oldIFS="$IFS"
IFS=$'\n' dirs=( $(find . -type d) ) 
IFS="$oldIFS"

Ou faites le manuellement:

IFS=" "$'\t\n '

Sinon, fermez simplement le terminal actuel. Votre nouvel appareil aura à nouveau le réglage IFS d'origine.

9
terdon