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

На самом деле это кажется намного проще, чем ответ, который был опубликован ранее. Вам просто нужно «sudo» знать, что вы находитесь за прокси-сервером, и он будет работать без усилий. Для этого вам нужно экспортировать свой прокси для http и https так, как вы обычно делаете:

export http_proxy=http://username:password@host:port/
export https_proxy=https://username:password@host:port/

, а затем добавить Defaults env_keep="https_proxy" в конец файла /etc/sudoers. После этого вы сможете добавить ppa с помощью команды:

sudo add-apt-repository ppa:the_ppa_you_want_to_add

или использовать

sudo -E add-apt-repository ppa:the_ppa_you_want_to_add

, если вы не хотите изменить файл /etc/sudoers. Параметр -E экспортирует переменные среды в пользователя sudo.

Я подробно рассказал об этом здесь, в своем блоге.

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

4 ответа

Использование 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
6
ответ дан 24 May 2018 в 14:08
  • 1
    Вопрос приобретает необычную популярность =) +1 – A.B. 15 June 2015 в 19:20
  • 2
    Мне нравится ваша команда tree ... Installed =) – A.B. 15 June 2015 в 19:39

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

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

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

И все. [!d2 ]

3
ответ дан 24 May 2018 в 14:08
  • 1
    Это довольно хорошо, но он будет разбивать имена файлов, содержащие новые строки – kos 15 June 2015 в 21:29
  • 2
    @kos нет, не будет. Shell globs может работать с новыми линиями без проблем. Ответ Суравэка будет ломаться на новостях, но только из-за sed. – terdon♦ 18 June 2015 в 01:01
  • 3
    @terdon, я бы сказал, что у него будет разрыв в расширении, в значительной степени похожий на ответ Сувавака на замену, это правда. @ Maythux Извинения, +1 затем – kos 18 June 2015 в 03:46

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

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

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

Объяснение [!d2 ] -regex ".*_+.*" Найти все файлы с хотя бы одним _ в имени файла _ Заменить все вхождения _ ... ... с символом пробела () [d14 ]

Пояснение

% 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
1
ответ дан 24 May 2018 в 14:08
  • 1
    Hmmm это работает, только если в имени файла есть максимум два символа подчеркивания. – kos 15 June 2015 в 19:30
  • 2
    @kos DOH Я старею – A.B. 15 June 2015 в 19:37
  • 3
    @kos ok, fixed =) – A.B. 15 June 2015 в 19:49
  • 4
    +1 для рекурсивного пути, однако сценарий OP применяется также к каталогам. Также здесь -regex действительно не нужен, -name "*_*" достаточно – kos 15 June 2015 в 20:01

Вот версия awk + для цикла:

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 также отображает текущий каталог (символизируется .), команда создаст побочный продукт - файл с ведущей точкой.

Добавление ! -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
ответ дан 24 May 2018 в 14:08

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

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