7 votes

AWK et les noms de fichiers contenant un espace.

J'essaie d'analyser des fichiers avec awk pour changer leurs noms. Tout se passait bien jusqu'à ce que je commence à le faire avec des fichiers dont le nom contient un espace. Les noms de fichiers sont quelque chose comme 11237_712312955_2012-01-04 18_31_03.wav et je veux remplacer le wav du nom du fichier. Voici un exemple de mon code :

ls | awk -F\. '{print $1}'

Après avoir exécuté ceci dans la console, tout est correct et j'obtiens le nom du fichier sans extension.

Exemple : fichier 11237_712312955_2012-01-04 18_31_03.wav

après ls | awk -F\. '{print $1}' dans la console que je reçois :

11237_712312955_2012-01-04 18_31_03 et c'est correct.

Mais quand je mets ça dans mon script :

#!/bin/bash
for i in $(ls);
do
  FILENAME=echo $i | awk -F\. '{print $1}'; #problematic line 
  echo $FILENAME
done

script scinde le fichier en deux à l'endroit où se trouvait l'espace.

La sortie de script est :

11237_712312955_2012-01-04
18_31_03

Comment faire pour que mon script fonctionne correctement ?

0 votes

Renommez vos fichiers pour supprimer les espaces. Sérieusement. Les espaces n'ont pas plus leur place dans les noms de fichiers que les tatouages dans le bas du dos.

0 votes

Oui, je le sais. J'ai enlevé les espaces après avoir conevrté et renommé les fichiers.

12voto

Eugene S Points 370

Le problème ici est l'analyse syntaxique avec ls . Pensez à jeter un coup d'œil ici : Pourquoi vous ne devriez pas analyser la sortie de ls. .

La raison pour laquelle vous ne devriez pas le faire est qu'UNIX autorise presque tous les caractères dans un nom de fichier, y compris les espaces, les nouvelles lignes, les virgules, les symboles pipe, et à peu près tout ce que vous essayez d'utiliser comme délimiteur, sauf NUL. Dans son mode par défaut, si la sortie standard n'est pas un terminal, ls sépare les noms de fichiers avec des nouvelles lignes. C'est très bien jusqu'à ce que vous ayez un fichier dont le nom contient une nouvelle ligne.

6voto

adaptr Points 16431

Oh mon dieu, c'est affreux.

Votre script utilise bash ; je vous suggère de faire ceci à la place :

#!/bin/bash
for i in *.wav; do mv "${i}" "${i%.wav}.ext"; done

Voir le Guide Bash pour plus de détails sur l'expansion des paramètres.

2voto

Mark Sonn Points 121

Vous pouvez essayer ceci.

awk '{print substr($0, index($0,$9))}'

Par exemple, voici la sortie de la commande ls :

-rw-r--r--. 1 root root 73834496 Dec 6 10:55 Fichier avec des espaces 2

Si vous utilisez un simple awk comme celui-ci

# awk '{print $9}'

Il ne renvoie que

# File

Si elle est utilisée avec la commande complète

# awk '{print substr($0, index($0,$9))}'

J'obtiens le résultat complet

Dossier avec espaces 2

Ici substr(s, a, b) : renvoie le nombre b de caractères de la chaîne s, à partir de la position a. Le paramètre b est facultatif.

Par exemple, si la correspondance est addr:192.168.1.133 et que vous utilisez substr comme suit

# awk '{print substr($2,6)}'

Vous obtenez l'IP, c'est-à-dire 192.168.1.133. Notez que le 6 est le caractère qui commence à partir de a dans l'adresse.

Ainsi, dans la commande correcte, $2 est $0 (ce qui imprime la ligne entière) et index($0,$9) correspond à $9 et imprime tout ce qui précède la colonne 9. Vous pouvez changer cela en index($0,$8) et voir que la sortie change en

# 10:55 File with spaces 2

`index(IN, FIND)'. Cette commande recherche dans la chaîne IN la première occurrence de la chaîne FIND, et renvoie la position en caractères où cette occurrence commence commence dans la chaîne IN.

J'espère que cela vous aidera. De plus, si vous assignez cette valeur à une variable dans le script alors vous devez mettre les variables entre guillemets. Sinon, vous obtiendrez des erreurs si vous effectuez une autre opération pour le nom du fichier extrait.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X