Ви зіткнетеся з деякими проблемами, якщо хочете одночасно перейменувати файли та каталоги. Перейменувати лише файл досить просто. Але ви хочете, щоб каталоги також були перейменовані. Ви не можете просто, mv Motörhead/Encöding Motorhead/Encoding
оскільки Motorhead
не буде існувати під час дзвінка.
Отже, нам потрібна перша глибина обходу всіх файлів і папок, а потім перейменування лише поточного файлу чи папки. Наступні роботи з GNU find
та Bash 4.2.42 на моїй ОС X.
#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
d="$( dirname "$file" )"
f="$( basename "$file" )"
new="${f//[^a-zA-Z0-9\/\._\-]/}"
if [ "$f" != "$new" ] # if equal, name is already clean, so leave alone
then
if [ -e "$d/$new" ]
then
echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
ls -ld "$d/$new" "$d/$f"
else
echo mv "$file" "$d/$new" # remove "echo" to actually rename things
fi
fi
done
Ви можете змінити регулярний вимір, використовуючи, new="${f//[\\\/\:\*\?\"<>|]/}"
якщо ви хочете замінити що-небудь, з чим Windows не може працювати.
Збережіть цей скрипт як rename.sh
, зробіть його виконуваним chmod +x rename.sh
. Потім, називайте це як rename.sh /some/path
.
Не забудьте вирішити будь-які зіткнення імен файлів (" Notice
" оголошення).
Якщо ви абсолютно впевнені, що він робить правильні заміни, видаліть echo
із сценарію, щоб насправді перейменувати речі, а не просто друкувати те, що він робить.
Для безпеки я рекомендую спершу протестувати це на невеликій підмножині файлів.
Варіанти пояснені
Щоб пояснити, що тут відбувається:
-depth
забезпечить, щоб каталоги повторювались по-перше, тому ми можемо "згортати" все з кінця. Зазвичай find
траверси йдуть по-різному (але не в першу чергу).
-print0
забезпечує find
вихід нуль-роздільниками, тому ми можемо прочитати його read -d ''
в file
змінної. Це допомагає нам мати справу з усіма видами дивних імен файлів, включаючи пробіли та навіть нові рядки.
- Ми отримаємо каталог файлу з
dirname
. Не забувайте завжди цитувати свої змінні належним чином, інакше будь-який шлях з пробілами чи символами глобуса порушить цей сценарій.
- Ми отримаємо фактичне ім’я файлу (або ім'я каталогу) за допомогою
basename
.
- Потім ми видаляємо будь-який недійсний символ з
$f
використанням можливостей заміни рядків Баша. Недійсне означає все, що не є малою чи малою літерою, цифрою, косою рисою ( \/
), крапкою ( \.
), підкресленням або мінус-дефісом.
- Якщо
$f
воно вже чисте (очищене ім’я тотожне назві), пропустіть його.
- Якщо
$new
в каталозі вже існує $d
(наприклад, у вас є файли з ім’ям resume
і résumé
в тому самому каталозі), надішліть попередження. Ви не хочете перейменовувати це, оскільки, в деяких системах, це mv foo foo
викликає проблеми. Інакше
- Ми нарешті перейменуємо оригінальний файл (або каталог) на його нове ім'я
Так як це буде діяти тільки на найглибшій ієрархії, перейменування Motörhead/Encöding
до Motorhead/Encoding
виконується в два етапи:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
Це забезпечує всі заміни в правильному порядку.
Приклад файлів та тестовий запуск
Припустимо, деякі файли в базовій папці під назвою test
:
test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule
Ось вихід із запуску в режимі налагодження (з echo
в передній частині mv
), тобто команди, які будуть викликані, та попередження про зіткнення:
mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r-- … … test/work/resume
-rw-r—r-- … … test/work/résumé
Зверніть увагу на відсутність повідомлень для with-hyphen.txt
, schedule
і test
саме по собі.
mv
вже існує, що може статися (1), якщо у вас вже є чисті файли (в результатіmv foo foo
), або (2), якщо у вас є файли з тим самим іменем, за винятком для спеціальних символів (наприклад,mv Encöding Encoding
де у вас уже єEncoding
файлEncöding
).