Использование sed для массового переименования файлов
Цель
Измените эти имена файлов:
- F00001-0708-RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
к этим именам файлов:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Код оболочки
Чтобы проверить:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
Для выполнения:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
Мой вопрос
Я не понимаю код sed. Я понимаю, что замена
Команда
$ sed 's/something/mv'
означает. И я понимаю регулярные выражения. Но я не
понять, что происходит здесь:
\(.\).\(.*\)
или здесь:
& \1\2/
Первый, для меня, просто выглядит так: "Один персонаж,
за которым следует один символ, за которым следует любая последовательность длин
один символ "- но, конечно же, для него это более важно.
последняя часть:
& \1\2/
Я понятия не имею. Я действительно хочу понять этот код. пожалуйста, помогите мне
здесь, ребята.
Ответы
Ответ 1
Во-первых, я должен сказать, что самый простой способ сделать это - использовать
команды prename или rename.
В Ubuntu, OSX (пакет Homebrew rename
, пакет MacPorts p5-file-rename
) или другие системы с perl rename (prename):
rename s/0000/000/ F0000*
или в системах с переименованием из util-linux-ng, таких как RHEL:
rename 0000 000 F0000*
Это намного понятнее, чем эквивалентная команда sed.
Но для понимания команды sed команда sed man помогает. Если
вы запускаете man sed и выполняете поиск и (используя команду/для поиска),
вы найдете его особым символом в s/foo/bar/replacement.
s/regexp/replacement/
Attempt to match regexp against the pattern space. If success‐
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
Следовательно, \(.\)
соответствует первому символу, на который может ссылаться \1
.
Тогда .
соответствует следующему символу, который всегда равен 0.
Затем \(.*\)
соответствует остальной части имени файла, на который можно ссылаться \2
.
Сменная строка ставит все вместе, используя &
(оригинал
filename) и \1\2
, который является каждой частью имени файла, за исключением второго
символ, который был равен 0.
Это довольно загадочный способ сделать это, ИМХО. Если для
по какой-то причине команда rename была недоступна, и вы хотели использовать
sed сделать переименование (или, возможно, вы делали что-то слишком сложное
для переименования?), более явное в вашем регулярном выражении сделало бы это
более читаемым. Возможно, что-то вроде:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Возможность увидеть, что на самом деле меняется в
s/search/replacement/делает его более читаемым. Также он не будет
высасывание символов из вашего имени файла, если вы случайно запустили его
дважды или что-то в этом роде.
Ответ 2
у вас появилось ваше объяснение sed, теперь вы можете использовать только оболочку, нет необходимости в внешних командах
for file in F0000*
do
echo mv "$file" "${file/#F0000/F000}"
# ${file/#F0000/F000} means replace the pattern that starts at beginning of string
done
Ответ 3
Самый простой способ:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
или, портативно,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Это заменяет префикс F00001
в именах файлов F0001
.
кредиты для mahesh здесь: http://www.debian-administration.org/articles/150
Ответ 4
Я написал небольшую запись с примерами переименования пакетов с помощью sed
пару лет назад:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Например:
for i in *; do
mv "$i" "`echo $i | sed "s/regex/replace_text/"`";
done
Если регулярное выражение содержит группы (например, \(subregex\
), вы можете использовать их в заменяющем тексте как \1\
, \2
и т.д.
Ответ 5
Команда sed
s/\(.\).\(.*\)/mv & \1\2/
означает замену:
\(.\).\(.*\)
с:
mv & \1\2
как обычная команда sed
. Однако скобки, метки &
и \n
немного меняют его.
Строка поиска соответствует (и запоминает как шаблон 1) одиночный символ в начале, за которым следует одиночный символ, оставленный остальной частью строки (запомнен как шаблон 2).
В строке замены вы можете ссылаться на эти сопоставленные шаблоны, чтобы использовать их как часть замены. Вы также можете ссылаться на всю согласованную часть как &
.
Итак, что делает эта команда sed
, это создание команды mv
, основанной на исходном файле (для источника) и символе 1 и 3 и далее, эффективно удаляя символ 2 (для адресата). Он даст вам ряд строк в следующем формате:
mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef
и т.д.
Ответ 6
Материал с обратной косой чертой означает, что "при совпадении с шаблоном держитесь за то, что соответствует здесь". Позже, на стороне замены текста, вы можете вернуть эти запомненные фрагменты с помощью "\ 1" (первый скобковый блок), "\ 2" (второй блок) и т.д.
Ответ 7
В скобках фиксируются определенные строки для использования с помощью обратных кодов.
Ответ 8
Если все, что вы действительно делаете, это удаление второго символа, независимо от того, что это такое, вы можете сделать это:
s/.//2
но ваша команда создает команду mv
и передает ее в оболочку для выполнения.
Это не более читаемо, чем ваша версия:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Четвертый символ удаляется, потому что find
добавляет каждое имя файла с помощью./".
Ответ 9
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
Ответ 10
Вот что я буду делать:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done
Затем, если это выглядит нормально, добавьте | sh
в конец. Итак:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done | sh