Как переименовать имена файлов - замена подчеркивания пробелами - в сценарии командной строки оболочки

Я пытаюсь переименовать все файлы в папке, заменяя подчеркивания пробелами.

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

но почему-то я испортил цитату

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

, которая выглядит нормально, но если я уберу 'echo' mv, то будет жаловаться, как будто удалены обратные слэши

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

Кто-то может указать на ошибку моих путей?

7
задан 26 August 2016 в 02:25

5 ответов

Есть небольшая ошибка. Используйте "$newfile" вместо только $newfile. Вам нужно использовать "

Вот правильный.

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

Если у вас есть имя файла this_is_a_test, оно переименует файл в this\ is\ a\ test.

В случае, если вы хотите переименовать файл в this is a test. Используйте приведенный ниже код,

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

Хорошей практикой является использование переменных внутри "" при написании хорошего сценария оболочки.

0
ответ дан 26 August 2016 в 02:25

Использование rename:

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

Если все в порядке, удалите переключатель -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
0
ответ дан 26 August 2016 в 02:25

Вместо mv -v "$file" "$(echo $file | sed 's/_/\\ /g')" вы можете использовать гораздо более простую команду mv "$f" "${f//_/ }".

Чтобы добавить его в свой скрипт:

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

И это все.

0
ответ дан 26 August 2016 в 02:25

Используйте команды find и rename:

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

Эта команда рекурсивно переименовывает весь файл с _ в имени файла.

Объяснение

  • -regex ".*_+.*"

    Найти все файлы с хотя бы одним _ в имени файла

  • _

    Заменить все вхождения _

  • … пробелом ( )


Пример

% 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
0
ответ дан 26 August 2016 в 02:25

Вот версия awk + for loop:

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

И вот она в действии

$ 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

Для учета перевода строки и возможного переименования каталогов Вот типичная конструкция цикла IFS + find + read + while. После выполнения предложения сначала запустите версию с find . -type d -print0, потому что если вы начнете сначала переименовывать файлы, а подкаталог содержит подчеркивание, имя файла не изменится. Короче говоря, сначала позаботьтесь о каталогах и подкаталогах, а затем позаботьтесь о файлах

$ 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

Как видите, есть небольшая проблема - потому что команда find также перечисляет текущий каталог (обозначается символом a. ) команда создаст побочный продукт - файл с начальной точкой.

Добавление ! -path . при работе с каталогами решает проблему

$ 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
ответ дан 26 August 2016 в 02:25

Другие вопросы по тегам:

Похожие вопросы: