Найти и заменить имя файла рекурсивно в каталоге - PullRequest
35 голосов
/ 22 февраля 2012

Я хочу переименовать все файлы в папке, которая начинается с 123_xxx.txt в xxx.txt.

Например, в моем каталоге:

123_xxx.txt
123_yyy.txt
123_zzz.txt

I want to rename all files as:

xxx.txt
yyy.txt
zzz.txt

Я видел некоторыеполезные скрипты bash на этом форуме, но я все еще не понимаю, как использовать его для моих требований.

Предположим, я использую:

for file in `find -name '123_*.txt'` ; do mv $file {?.txt} ; done

Это правильный способ сделать это?

Ответы [ 12 ]

67 голосов
/ 22 февраля 2012

Сделайте это следующим образом:

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

Преимущества:

  • Нет каналов, нет чтения, нет шансов разбить искаженные имена файлов.
  • Только одиннестандартный инструмент или функция: bash.
21 голосов
/ 22 февраля 2012
find -name "123*.txt" -exec rename 's/^123_//' {} ";" 

сделает это.Нет AWK, нет for, xargs не требуется, но rename , очень полезная команда из библиотеки Perl.Он не всегда включен в Linux, но его легко установить из репозитория.

7 голосов
/ 28 июля 2015

Если вы хотите заменить строку в имени файла с именем foo на bar, вы можете использовать ее в linux ubuntu, измените тип файла для своих нужд

find -name "*foo*.filetype" -exec rename 's/foo/bar/' {} ";"
7 голосов
/ 22 февраля 2012

вы можете проверить инструмент переименования

например

rename 's/^123_//' *.txt

или (необходим gawk)

find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

тест :

kent$  tree
.
|-- 123_a.txt
|-- 123_b.txt
|-- 123_c.txt
|-- 123_d.txt
|-- 123_e.txt
`-- u
    |-- 123_a.txt
    |-- 123_b.txt
    |-- 123_c.txt
    |-- 123_d.txt
    `-- 123_e.txt

1 directory, 10 files

kent$  find . -name '123_*.txt'|awk '{print "mv "$0" "gensub(/\/123_(.*\.txt)$/,"/\\1","g");}'|sh

kent$  tree
.
|-- a.txt
|-- b.txt
|-- c.txt
|-- d.txt
|-- e.txt
`-- u
    |-- a.txt
    |-- b.txt
    |-- c.txt
    |-- d.txt
    `-- e.txt

1 directory, 10 files
3 голосов
/ 22 февраля 2012

Небольшое изменение на Кента, который не требует Gawk и немного более удобным для чтения, (хотя, тот спорно ..)

find . -name "123*" | awk '{a=$1; gsub(/123_/,""); printf "mv \"%s\" \"%s\"\n", a, $1}' | sh

2 голосов
/ 22 февраля 2012

При условии, что в именах файлов нет новых строк:

find -name '123_*.txt' | while IFS= read -r file; do mv "$file" "${file#123_}"; done

Для действительно безопасного пути, если ваш find поддерживает флаг -print0 (GNU find поддерживает):

find -name '123_*.txt' -print0 | while IFS= read -r -d '' file; do mv "$file" "${file#123_}"; done
1 голос
/ 20 февраля 2016

Вы можете сделать небольшой сценарий bash для этого. Создайте файл с именем recursive_replace_filename с таким содержанием:

#!/bin/bash

if test $# -lt 2; then
  echo "usage: `basename $0` <to_replace> <replace_value>"
fi

for file in `find . -name "*$1*" -type f`; do
  mv "'$file'" "${file/'$1'/'$2'}"
done

Сделать исполняемый файл прогоном:

$ chmod +x recursive_replace_filename
$ ./recursive_replace_filename 123_ ""

Имейте в виду, что этот сценарий может быть опасным, убедитесь, что вы знаете, что он делает, в какой папке вы его выполняете и с какими аргументами. В этом случае все файлы в текущей папке, рекурсивно содержащие 123_, будут переименованы.

1 голос
/ 03 марта 2015

Чтобы расширить на ответ Сорпигала , если вы хотите заменить 123_ на hello_, вы можете использовать

    find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "${1/\/123_/\/hello_}"' -- {} \;
0 голосов
/ 30 января 2019

Если имена фиксированы, вы можете посетить каждый каталог и выполнить переименование в подоболочке (чтобы избежать изменения текущего каталога) довольно просто.Вот как я переименовал группу файлов new_paths.json каждый в paths.json:

for file in $(find root_directory -name new_paths.json)
  do
     (cd $(dirname $file) ; mv new_paths.json paths.json)
  done
0 голосов
/ 18 декабря 2018

Попробовал ответ выше, но он не сработал для меня, потому что у меня была строка внутри папок и имен файлов одновременно, вот что я сделал следующим скриптом bash:

  for fileType in d f
  do
    find  -type $fileType -iname "stringToSearch*" |while read file
    do
      mv $file $( sed -r "s/stringToSearch/stringToReplaceWith/" <<< $file )
    done
  done

Первыйя начал с замены внутри имени папки, а затем внутри имени файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...