Як замінити пробіли у всіх іменах файлів на підкреслення в Linux за допомогою скрипту оболонки?


17

Я спробував наступний скрипт оболонки, який повинен замінити пробіли з усіх файлів xml

for xml_file in $(find $1 -name "* .xml" -type f);
do
 echo "removing spaces from XML file:" $xml_file
 mv "$xml_file" "${xml_file// /_}";
done

Припустимо, у мене є файл xml з ім'ям xy z.xml, то він дає:

removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat `/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat `z.xml': No such file or directory

Відповіді:


29

Використовуйте це для bash:

find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done

findбуде шукати файли з пробілом у назві. Імена файлів будуть надруковані з нульбайтом ( -print0) як роздільник, щоб також впоратися зі спеціальними іменами. Потім readвбудований читає назви файлів, відмежовані нульбайтом, і, нарешті, mvзамінює пробіли підкресленням.

EDIT: Якщо ви теж хочете видалити пробіли в каталогах, це трохи складніше. Каталоги перейменовані, а потім вже не доступні за назвою findзнахідок. Спробуйте це:

find -name "* *" -print0 | sort -rz | \
  while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

sort -rzЗмінює порядок файлу, так що найглибші файли в папці є першими для переміщення і сама папка буде останнім. Отже, ніколи не перейменовані папки, перш ніж усі файли та папки будуть перейменовані всередині неї. mvКоманда в циклі трохи змінився теж. У цільовому імені ми видаляємо лише пробіли в базовій імені файлу, інакше він не був би доступний.


Я намагаюся замінити пробіли з підкресленням у всіх каталогах, але він видає помилку, оскільки після зміни імені цей каталог недоступний.
кришна

@krishna Я додав редагування до своєї відповіді.
хаос

1
@chaos вау, щойно запустив цих двох на двох системах, і це спрацювало як шарм, кілька файлів і файлів не переживає, але це лише декілька
щось щось

На macOS нам потрібно вказати каталог у команді find перед опцією -name find . -name "* *" -print0 | sort -rz | \ while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
Laszlo Pinter

17
  1. Використання rename

    find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;

    або з $1

    find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
  2. Використання mv

    find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

    або з $1

    find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

Я не знаю чому, але ваша дана команда не працює для мене. Це не відображає помилок та результатів.
Крішна

@krishna виправлено, вибачте
AB

1
Перейменування працювало на мене. Fistbump!
Брайан Пірсі

1

Це метод, який я знайшов, стикаючись з тією ж проблемою:

for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done

Я писав файл скрипту bash для автоматичного оновлення своїх сертифікатів ssl.


1

Використання rename:

rename 's/\s/_/g' ./*.xml

Не потрібно find:)


1
додайте зворотний g до регулярного виразу, і він відмінно працює. 's / \ s / _ / g'
jbrahy

Гарна порада, дякую :)
Ян Верховен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.