IDK, если rename
может работать рекурсивно. Я сделал несколько пустых файлов с пробелами (s )в именах внутри подкаталога без пробела и один с. Приведенное ниже работает для меня, чтобы переименовать файлы с одним или несколькими пробелами в именах с одним подчеркиванием и не беспокоит подкаталог с пробелами в его имени.
root@server <1>: /cwd# mkdir subdir1 'sub dir 2' ; touch 'subdir1/file 1' 'sub dir 2/file 2 ' 'subdir1/ f i l e 3 ' 'sub dir 2/ f i l e 4 '
root@server <2>: /cwd# ls -lhR
.:
total 0
drwxr-xr-x 2 root root 80 Dec 28 00:42 subdir1
drwxr-xr-x 2 root root 80 Dec 28 00:42 'sub dir 2'
./subdir1:
total 0
-rw-r--r-- 1 root root 0 Dec 28 00:42 'file 1'
-rw-r--r-- 1 root root 0 Dec 28 00:42 ' f i l e 3 '
'./sub dir 2':
total 0
-rw-r--r-- 1 root root 0 Dec 28 00:42 'file 2 '
-rw-r--r-- 1 root root 0 Dec 28 00:42 ' f i l e 4 '
root@server <3>: /cwd# find. -type f -exec echo {} \; | tee../FILES.txt
./sub dir 2/ f i l e 4
./sub dir 2/file 2
./subdir1/ f i l e 3
./subdir1/file 1
root@server <4>: /cwd# while IFS= read line ; do
> dirname="${line%/*}"
> fn=${line##*/}
> fn="${fn//+( )/_}"
> mv -v "$line" "${dirname}/${fn}"
> done <../FILES.txt
renamed './sub dir 2/ f i l e 4 ' -> './sub dir 2/_f_i_l_e_4_'
renamed './sub dir 2/file 2 ' -> './sub dir 2/file_2_'
renamed './subdir1/ f i l e 3 ' -> './subdir1/_f_i_l_e_3_'
renamed './subdir1/file 1' -> './subdir1/file_1'
root@server <5>: /cwd# ls -lhR
.:
total 0
drwxr-xr-x 2 root root 80 Dec 28 00:42 subdir1
drwxr-xr-x 2 root root 80 Dec 28 00:42 'sub dir 2'
./subdir1:
total 0
-rw-r--r-- 1 root root 0 Dec 28 00:42 file_1
-rw-r--r-- 1 root root 0 Dec 28 00:42 _f_i_l_e_3_
'./sub dir 2':
total 0
-rw-r--r-- 1 root root 0 Dec 28 00:42 file_2_
-rw-r--r-- 1 root root 0 Dec 28 00:42 _f_i_l_e_4_
Некоторые примечания по каждой команде:
создает два подкаталога, в имени второго из которых есть пробелы.
рекурсивно перечисляет содержимое. обратите внимание, что одинарные кавычки используются для файлов или папок, содержащих пробелы.
используйте find
для поиска файлов(-type f
)и повторите имя в «FILES.txt» в родительском каталоге.
используйте цикл while
для перебора каждой строки в файле. IFS=
очищает разделитель полей ввода, поэтому начальные и конечные пробелы не усекаются.
4.1 извлекает имя каталога, которое не следует изменять
4.2 получает имя файла
4.3 заменяет один или несколько последовательных пробелов одним символом подчеркивания в имени файла
4.4 подробно переименовывает файлы, но не папки.
рекурсивно перечисляет содержимое. обратите внимание, что одинарные кавычки используются для файлов или папок, содержащих пробелы.
Я использовал расширение параметров для получения имен каталогов и имен файлов вместо dirname
и basename
, потому что это быстрее.