J'essaie de construire un tableau en bash des noms de fichiers de ma caméra:
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
Comme vous pouvez le voir, il y a un espace au milieu de chaque nom de fichier.
J'ai essayé de mettre chaque nom entre guillemets et d'échapper à l'espace avec une barre oblique inverse, ce qui ne fonctionne pas.
Lorsque j'essaie d'accéder aux éléments du tableau, il continue de traiter l'espace comme le délimiteur d'élément.
Comment puis-je capturer correctement les noms de fichiers avec un espace à l'intérieur du nom?
FILES[0] = ...
? (Edit: je viens de le faire; ne fonctionne pas. Intéressant).find . -maxdepth 1 -type f -iname \*.$1 -printf '%f\n'
); pour l'élément dans $ {array [@]}; faire echo $ element; doneRéponses:
Je pense que le problème tient peut-être en partie à la manière dont vous accédez aux éléments. Si je fais un simple
for elem in $FILES
, je rencontre le même problème que vous. Cependant, si j'accède au tableau via ses indices, comme ça, cela fonctionne si j'ajoute les éléments soit numériquement ou avec des échappements:Chacune de ces déclarations de
$FILES
devrait fonctionner:ou
ou
la source
echo "${FILES[$i]}"
). Cela n'a pas d'importanceecho
, mais ce sera pour tout ce qui l'utilise comme nom de fichier.for f in "${FILES[@]}"
.#
symbole sharp ( ) dans l'for ((i = 0; i < ${#FILES[@]}; i++))
instruction?Il doit y avoir un problème avec la façon dont vous accédez aux éléments du tableau. Voici comment procéder:
Depuis la page de manuel bash :
Bien sûr, vous devez également utiliser des guillemets doubles lors de l'accès à un seul membre
la source
expands to a single word with the value of each array member separated by the first character of the IFS special variable
for elem in "${files[@]}"
alors qu'ils ontfor elem in ${files[@]}
- donc les espaces confondent l'expansion et pour les essais en cours d'exécution sur les mots individuels.Vous devez utiliser IFS pour arrêter l'espace comme délimiteur d'élément.
Si vous souhaitez vous séparer sur la base de. alors faites simplement IFS = "." J'espère que cela vous aide :)
la source
IFS=""
avant la construction du tableau .Je suis d'accord avec les autres pour dire que c'est probablement la façon dont vous accédez aux éléments qui pose problème. La citation des noms de fichier dans l'affectation de tableau est correcte:
L'utilisation de guillemets doubles autour de n'importe quel tableau du formulaire
"${FILES[@]}"
divise le tableau en un mot par élément de tableau. Cela ne divise pas les mots au-delà de cela.L'utilisation a
"${FILES[*]}"
également une signification particulière, mais elle joint les éléments du tableau avec le premier caractère de $ IFS, ce qui donne un mot, ce qui n'est probablement pas ce que vous voulez.En utilisant un nu
${array[@]}
ou${array[*]}
soumet le résultat de cette expansion à un fractionnement supplémentaire des mots, vous vous retrouverez donc avec des mots divisés sur des espaces (et tout ce qui s'y trouve$IFS
) au lieu d'un mot par élément du tableau.Utiliser une boucle for de style C est également très bien et évite de s'inquiéter de la division des mots si vous n'êtes pas clair:
la source
Des œuvres qui s'échappent.
Production:
Le fait de citer les chaînes produit également la même sortie.
la source
Si vous aviez votre tableau comme ceci: #! / Bin / bash
Vous obtiendrez:
Je ne sais pas pourquoi mais la boucle décompose les espaces et les place comme un élément individuel, même si vous l'entourez de guillemets.
Pour contourner ce problème, au lieu d'appeler les éléments du tableau, vous appelez les index, qui prennent la chaîne complète entourée de guillemets. Il doit être entouré de guillemets!
Ensuite, vous obtiendrez:
la source
Pas exactement une réponse au problème de citation / échappement de la question originale mais probablement quelque chose qui aurait en fait été plus utile pour l'opération:
Où bien sûr l'expression devrait être adaptée à l'exigence spécifique (par exemple
*.jpg
pour tous ou2001-09-11*.jpg
pour seulement les images d'un certain jour).la source
Une autre solution consiste à utiliser une boucle «while» à la place d'une boucle «for»:
la source
Si vous n'êtes pas coincé dans l'utilisation
bash
, la gestion différente des espaces dans les noms de fichiers est l'un des avantages de la coquille de poisson . Prenons un répertoire contenant deux fichiers: "a b.txt" et "b c.txt". Voici une estimation raisonnable du traitement d'une liste de fichiers générés à partir d'une autre commande avecbash
, mais cela échoue en raison d'espaces dans les noms de fichiers que vous avez rencontrés:Avec
fish
, la syntaxe est presque identique, mais le résultat est ce à quoi vous vous attendez:Cela fonctionne différemment parce que le poisson divise la sortie des commandes sur les nouvelles lignes, pas sur les espaces.
Si vous avez un cas où vous souhaitez fractionner sur des espaces au lieu de nouvelles lignes,
fish
a une syntaxe très lisible pour cela:la source
J'avais l'habitude de réinitialiser la valeur IFS et de revenir en arrière une fois terminé.
Sortie possible de la boucle:
la source