web-dev-qa-db-fra.com

Comment renommer des noms de fichiers - remplacer les caractères de soulignement par des espaces - dans un script de ligne de commande Shell

J'essaie de renommer tous les fichiers d'un dossier en remplaçant les caractères de soulignement par des espaces.

i.e. this_is_a_test --> this is a test

mais de toute façon je foiré la citation

> for file in * ; do echo mv -v $file $(echo $file | sed 's/_/\\ /g') ; done
mv -v this_is_a_test this\ is\ a\ test

ça a l'air correct, mais si je supprime 'echo' mv se plaint comme si les barres obliques inverses avaient été supprimées

> for file in * ; do mv -v $file $(echo $file | sed 's/_/\\ /g') ; done
mv: target ‘test’ is not a directory

Quelqu'un peut-il signaler l'erreur de mes manières?

7
ottotts

Il y a une erreur mineure. Utilisez "$newfile" au lieu de $newfile. Vous devez utiliser "

Voici le bon.

for file in * ; do mv -v "$file" "$(echo $file | sed 's/_/\\ /g')" ; done

Si vous avez le nom de fichier this_is_a_test, le fichier sera renommé en this\ is\ a\ test.

Dans le cas où vous souhaitez renommer le fichier en this is a test. Utilisez le code ci-dessous,

for file in * ; do mv -v "$file" "$(echo $file | sed 's/_/ /g')" ; done

Il est recommandé d’utiliser des variables dans "" lors de l’écriture d’un bon script Shell.

3
souravc

Utilisation de rename:

rename -n 's/_/ /g' *

Si tout va bien, supprimez le commutateur -n:

rename 's/_/ /g' *
~/tmp$ tree
.
├── file
├── file_1
├── file_2
├── file_3
└── file_with_underscores

0 directories, 5 files
~/tmp$ rename 's/_/ /g' *
~/tmp$ tree
.
├── file
├── file 1
├── file 2
├── file 3
└── file with underscores

0 directories, 5 files
7
kos

Au lieu de mv -v "$file" "$(echo $file | sed 's/_/\\ /g')", vous pouvez utiliser une commande beaucoup plus simple, mv "$f" "${f//_/ }".

Pour l'ajouter dans votre script:

for f in * ; do mv "$f" "${f//_/ }" ; done

Et c'est tout.

3
Maythux

Utilisez les commandes find et rename:

find <your_start_folder> -type f -regex ".*_+.*" -exec rename 's/_/ /g' {}  \;

Cette commande renomme tous les fichiers avec un _ dans le nom de fichier de manière récursive.

Explication

  • -regex ".*_+.*"

    Trouver tous les fichiers avec au moins un _ dans le nom du fichier

  • _

    Remplacez toutes les occurrences de _

  • … Avec un caractère d'espacement ()


Exemple

% ls -Rog
.:
total 4
drwxrwxr-x 2 4096 Jun 15 17:39 foo
-rw-rw-r-- 1    0 Jun 15 17:34 foo_bar

./foo:
total 0
-rw-rw-r-- 1 0 Jun 15 17:32 foo_bar

% find . -type f -regex ".*_+.*" -exec rename 's/_/ /g' {} \;

% ls -Rog                                                                 
.:
total 4
drwxrwxr-x 2 4096 Jun 15 17:40 foo
-rw-rw-r-- 1    0 Jun 15 17:34 foo bar

./foo:
total 0
-rw-rw-r-- 1 0 Jun 15 17:32 foo bar
2
A.B.

Voici une version de awk + for loop:

for filename in *; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done

Et le voici en action

$ ls                                                                                                                                                  

$ echo "TEST" | tee {foo,bar}_{yolo,Swag}_{whatever,else}.txt                                                                                         
TEST

$ ls
bar_Swag_else.txt      bar_yolo_else.txt      foo_Swag_else.txt      foo_yolo_else.txt
bar_Swag_whatever.txt  bar_yolo_whatever.txt  foo_Swag_whatever.txt  foo_yolo_whatever.txt

$ for filename in *; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                    

$ ls
bar Swag else.txt      bar yolo else.txt      foo Swag else.txt      foo yolo else.txt
bar Swag whatever.txt  bar yolo whatever.txt  foo Swag whatever.txt  foo yolo whatever.txt

Pour prendre en compte les nouvelles lignes et le renommage possible des répertoires, voici la construction de boucle IFS + find + read + while typique. Une fois la suggestion terminée, lancez d'abord la version avec find . -type d -print0, car si vous commencez par renommer des fichiers et qu'un sous-répertoire contient un trait de soulignement, le nom du fichier ne sera pas modifié. En bref, s’occuper des répertoires et des sous-répertoires d’abord, puis des fichiers

$ ls
file_bar_Swag.txt  file_bar_yolo.txt  file_test_Swag.txt  file_test_yolo.txt  foo_bar_Swag.txt  foo_bar_yolo.txt  foo_test_Swag.txt  foo_test_yolo.txt  tester_dir

$ ls tester_dir/                                                                                                                                                                                         
ber_sweg_elze.txt  ber_sweg_whut.txt  ber_yelo_elze.txt  ber_yelo_whut.txt  fee_sweg_elze.txt  fee_sweg_whut.txt  fee_yelo_elze.txt  fee_yelo_whut.txt

$  find . -type d -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done 
mv: ‘.’ and ‘./.’ are the same file

$ ls
file_bar_Swag.txt  file_bar_yolo.txt  file_test_Swag.txt  file_test_yolo.txt  foo_bar_Swag.txt  foo_bar_yolo.txt  foo_test_Swag.txt  foo_test_yolo.txt  tester dir

$  find . -type f -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                          
mv: ‘./.yolo’ and ‘./.yolo’ are the same file

$ ls
file bar Swag.txt  file bar yolo.txt  file test Swag.txt  file test yolo.txt  foo bar Swag.txt  foo bar yolo.txt  foo test Swag.txt  foo test yolo.txt  tester dir

Comme vous pouvez le constater, il existe un petit problème: comme la commande find répertorie également le répertoire courant (symbolisé par un.), Elle créera un sous-produit - un fichier avec un point en tête.

Ajouter ! -path . lorsque vous traitez avec des répertoires résout le problème

$ find . ! -path .  -type d -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                

$ find .  -type f -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                          

$ ls
file bar Swag.txt  file bar yolo.txt  file baz Swag.txt  file baz yolo.txt  foo bar Swag.txt  foo bar yolo.txt  foo baz Swag.txt  foo baz yolo.txt  tester dir

$ ls "tester dir"
file bar.txt  file baz.txt  foo bar.txt  foo baz.txt

$ ls -a
.  ..  file bar Swag.txt  file bar yolo.txt  file baz Swag.txt  file baz yolo.txt  foo bar Swag.txt  foo bar yolo.txt  foo baz Swag.txt  foo baz yolo.txt  tester dir
0