Переименование файлов из верхний регистр в нижний регистр

Как насчет объединения смежных пар строк, а затем использования обратной ссылки для поиска неуникального префикса?

$ sed '$!N; /\(.*\)\n\1:FOO/D; P;D' file
red.7
green.2:FOO
blue.6
yellow.9:FOO

Объяснение:

  • $!N - если мы еще не на последней строке, добавляем следующую строку к пробелу шаблона, разделенному новой строкой
  • /\(.*\)\n - сопоставляем все до новой строки (т.е. первая из каждой пары строк) и сохранить в группу захвата
  • \1:FOO теперь соответствует всему, что было захвачено из первой строки, а затем :FOO (\1 является обратной ссылкой на первую группу захвата)
  • /\(. *\)\n\1:FOO/D - если вторая строка каждой пары такая же, как и первая, за которой следует :FOO, то Dудалите первую
  • Print и Dудалите оставшуюся строку, готовую начать следующий цикл

или более аккуратно (спасибо @don_crissti)

 sed '$! N; /\(.*\)\n\1:FOO/!P;D' файл'

N означает, что в пространстве шаблона всегда есть две последовательные строки и sed Pринтирует первую из них, только если вторая строка не является такая же, как первая, плюс суффикс :FOO. Затем D удаляет первую удаляет первую строку из пространства шаблона и начинает цикл заново.

3
23.07.2016, 07:41
7 ответов

Простой сценарий rename-lower для текущего каталога, если команда rename не работает, вы можете изменить ее в mv .

#/bin/bash
# script to replace all upper case to lower case
for i in *
do
        d=$(echo ${i} |tr [:upper:] [:lower:]);
        if [ ${d} != ${i} ]
        then
                echo "renaming:" ${i} ${d}
                rename ${i} ${d} ${i}
#               mv ${i} ${d}
        fi
done

Пример

$ ls
tmp.EwcM2s6kfU  tmp.kcUX6rtjiu  tmp.kzpqLvWcnQ  tmp.N1H8bLt1at

$ rename-lower
renaming: tmp.EwcM2s6kfU  tmp.ewcm2s6kfu
renaming: tmp.kcUX6rtjiu  tmp.kcux6rtjiu
renaming: tmp.kzpqLvWcnQ  tmp.kzpqlvwcnq
renaming: tmp.N1H8bLt1at  tmp.n1h8blt1at
1
27.01.2020, 21:09

Этот ответ от Alex B из Stack Overflow поможет вам переименовать как файлы, так и подпапки в каталоге.

Он заключается в использовании команд Linux find и rename . Я бы только добавил, что команда, указанная в приведенной выше ссылке, также изменит имена каталогов. Если вы хотите изменить только имена файлов, вам нужно изменить параметр -depth на следующий: -type f .

Еще одно регулярное выражение, данное команде rename , может быть приведенным ниже, и я думаю, что его легче понять.

 find my_root_dir -type f -execdir rename 'y/A-Z/a-z/' {} \;

Имейте в виду, что между регулярным выражением команды переименовать и фигурными скобками есть необходимый пробел, а между ними и символом завершения команды \;

Также помните, что он переименует каждый файл не только в каталоге, из которого вы выполняете команду (каталог my_root_dir ), но также и во все файлы в каждой подпапке, содержащейся в этом. Вы можете использовать опцию -maxdepth 0 с командой find , чтобы заставить ее применять тесты и действия только к самим начальным точкам.

2
27.01.2020, 21:09

Вот:

for i in $( ls | grep [A-Z] ); do mv -f $i `echo $i | tr 'A-Z' 'a-z'`; done

А это пример, показывающий, как это работает:

X$ ls

123123HHHSK FILE_[1-10] DB
FILE1       FILE_{1-10} SQL

X$ for i in $( ls | grep [A-Z] ); do mv -f $i `echo $i | tr 'A-Z' 'a-z'`; done

X$ ls

123123hhhsk file_[1-10] db
file1       file_{1-10} sql 

EDIT: Мы могли бы легко использовать опцию -f, чтобы избежать использования yes y.

1
27.01.2020, 21:09

Ваша команда mv не работает так, как задумано, потому что происходит расширение подстановочных знаков, и в результате получается один список имен файлов, который передается в mv. Синтаксис mv следующий mv SOURCE1 SOURCE2 ... DESTINATION, т.е. все аргументы, кроме последнего, являются именами файлов, которые должны быть перемещены в место назначения. mv не поддерживает переименование на основе шаблонов.

Если у вас есть утилита prename, вы можете использовать ее для переименования файлов, выполняя Perl-код для каждого имени. Синтаксис: prename PERL-CODE FILENAME1 FILENAME2 .... Имя файла находится в переменной $_, а функция lc преобразует его аргумент в нижний регистр, поэтому можно использовать следующий код:

prename '$_ = lc($_)' /home/imp/hpt/outbound/[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z].[STFWMfWM][OUAHER][0-9]

Если у вас нет этой утилиты, вы можете загрузить версию с CPAN.

В качестве альтернативы, вы можете выполнить переименование в оболочке, используя цикл. В bash вы можете использовать ${x,,}, чтобы получить значение x, преобразованное в нижний регистр.

for x in /home/imp/hpt/outbound/[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z].[STFWMfWM][OUAHER][0-9]; do
  mv "$x" "${x,,}"
done
1
27.01.2020, 21:09

С zsh :

autoload zmv # best in ~/.zshrc
zmv '[[:alnum:]](#c8).[STFWMfWM][OUAHER][0-9]' '${(L)f}'

Это позволит проверить наличие потенциальных конфликтов.

2
27.01.2020, 21:09

Если вы хотите заменить один класс символов на другой, используйте tr .

for f in *; do
    test -f "$f" && echo mv "$f" "$( tr '[:upper:]' '[:lower:]' <<<"$f" )"
done

Сценарий переименует все файлы в текущем каталоге в строчные буквы. Каталоги будут пропущены. Удалите echo , когда вы уверены, что оно делает то, что вы хотите. Вы можете заменить [: upper:] и [: lower:] на AZ и az соответственно, если у вас есть только стандартные имена файлов ASCII. (примечание: AZ , а не [AZ] ).

В качестве альтернативы можно использовать встроенную в Bash подстановку переменных с верхнего на нижний регистр:

for f in *; do
    test -f "$f" && echo mv "$f" "${f,,}"
done
6
27.01.2020, 21:09

Следующее сработало для меня:

    for f in *; do mv -T "$f" "$(echo $f | tr [A-Z] [a-z])"; done

Было бы интересно, какие проблемы с моим решением.

0
27.01.2020, 21:09

Теги

Похожие вопросы