2009-10-14 7 views
2

Supposons que j'ai une liste de fichierspoignée de caractères spéciaux dans bash pour ... dans la boucle

file1 
"file 1" 
file2 

a pour ... dans la boucle il se brise entre les espaces, non: nouvelles lignes

for x in $(ls); do 
    echo $x 
done 

résultats:

file 
1 
file1 
file2 

Je veux exécuter une commande sur chaque fichier. "fichier" et "1" ci-dessus ne sont pas des fichiers réels. Comment puis-je faire cela si les noms de fichiers contiennent des choses comme des espaces ou des virgules?

C'est un peu plus compliqué que je pense trouver -print0 | xargs -0 pourrait gérer, parce que je veux vraiment que la commande soit quelque chose comme "convert input/file1.jpg .... output/file1.jpg" donc j'ai besoin de permuter le nom de fichier dans le processus.

Répondre

2

MISE À JOUR PAR OP: cette réponse est nulle et ne devrait pas être au top ... @ Le post de Jordan ci-dessous devrait être la réponse acceptée.

une façon possible:

ls -1 | while read x; do 
    echo $x 
done 

+0

@ ʞɔıu, si la réponse est fausse, alors vous pouvez non l'accepter afin qu'il n'induire en erreur qui que ce soit. – codeforester

+0

@codeforester - J'ai fait le montage en disant la réponse aspirée, pas ʞɔıu. – eduffy

8

En fait, la suggestion de Mark fonctionne très bien sans même faire quoi que ce soit au séparateur de champ interne. Le problème est l'exécution de ls dans un sous-shell, que ce soit par backticks ou $() provoque la boucle for à être incapable de faire la distinction entre les espaces dans les noms. Le simple fait d'utiliser

for f in * 

à la place de ls résout le problème.

#!/bin/bash 
for f in * 
do 
echo "$f" 
done 
+0

Jordan, je n'ai vu aucun problème avec la solution d'eduffy. J'ai essayé avec des fichiers qui avaient des espaces en eux. En fait, ls -1 ne crée pas de sous-shell. Cela crée simplement un autre processus, c'est tout. – codeforester

+0

Je suis d'accord, ça marche très bien pour moi. Honnêtement, étant donné que j'ai fait ce commentaire et le fait qu'il y ait une réponse à laquelle je me réfère de "Mark" qui manque, je pense que certains contextes ont été perdus et pourraient avoir plus de sens. @ La solution d'eduffy est très bien, le processus supplémentaire n'est pas un gros problème mais si l'automatisation sur un très grand nombre d'emplacements,/peut-être/ce serait un peu plus lent, mais je doute que ce soit un problème réel monde. – Jordan

0

Je sais celui-ci est passé depuis longtemps « répondu », et avec tout le respect dû à eduffy, je suis venu avec une meilleure façon et je pensais que je partage. Ce qui est "faux" avec la réponse d'eduffy n'est pas que c'est faux, mais qu'il impose ce qui est pour moi une limitation douloureuse: il y a une création implicite d'un sous-shell lorsque la sortie du ls est canalisée et cela signifie que les variables mis à l'intérieur de la boucle sont perdus après la sortie de la boucle. Ainsi, si vous voulez écrire un code plus sophistiqué, vous avez mal aux fesses à traiter.

Ma solution était de prendre la « readline » fonction et écrire un programme sur dans lequel vous pouvez spécifier un numéro de ligne spécifique que vous voudrez peut-être que les résultats de tout appel de fonction donnée. ... A titre d'exemple simple, en commençant par son eduffy:

ls_output=$(ls -1) 
# The cut at the end of the following line removes any trailing new line character 
declare -i line_count=$(echo "$ls_output" | wc -l | cut -d ' ' -f 1) 
declare -i cur_line=1 
while [ $cur_line -le $line_count ] ; 
do 
    # NONE of the values in the variables inside this do loop are trapped here. 
    filename=$(echo "$ls_output" | readline -n $cur_line) 
    # Now line contains a filename from the preceeding ls command 
    cur_line=cur_line+1 
done 

Maintenant, vous avez enveloppé toute l'activité de sous-shell dans peu propre contenu des paquets et peut aller sur votre codage shell sans avoir à se soucier de la portée de votre variable valeurs se coincer dans les sous-couches.

J'ai écrit ma version de readline dans gnuc si quelqu'un veut une copie, c'est un peu gros à poster ici, mais peut-être que nous pouvons trouver un moyen ...

Hope this helps, RT

Questions connexes