Получить все имена файлов с определенным количеством символов

Я хочу изменить все имена файлов, они имеют точную длину 16 символов (цифры и строчные буквы). Я попробовал [0-9a-z]{16} и [0-9a-z]\{16\} для регистратора placeholder в следующем фрагменте, но он не работает.

 for file in <regX> do mv "$file" "${file}.txt" done 

  • Переименовать файлы в индекс
  • Что делает «-t» в команде mv? Пример ниже
  • Переместить только при проверке?
  • Почему cp / mv не может быть прервано до конца текущего файла
  • bash перемещение скрытых файлов, сброс dotglob?
  • Линейные системные файлы перемещены, как вернуться при загрузке с установщика?
  • Как я могу перемещать файлы и просматривать прогресс (например, с индикатором выполнения)?
  • Как определить исходное местоположение файла?
  • 4 Solutions collect form web for “Получить все имена файлов с определенным количеством символов”

    С extglob

     shopt -s extglob for file in +([0-9a-z]) do [[ ${#file} == 16 ]] && echo mv "$file" "${file}.txt" done 
    • +([0-9a-z]) означает один или несколько [0-9a-z]
    • ${#file} дает длину имени файла
    • echo для сухого пробега, удалите, когда все будет в порядке

    Шаблоны оболочки не являются регулярными выражениями . Они могут выглядеть похожими, но в некоторых отношениях они работают по-разному.

    Регулярное выражение [0-9a-z]{16} соответствует строке, содержащей пробег из 16 символов указанного диапазона символов (строка, содержащая совпадение, может быть длиннее).

    Эквивалентный шаблон шаблона оболочки будет чем-то вроде

     *[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]* 

    Это потому что

    1. Шаблоны глобусов не поддерживают модификаторы, которые говорят «повторить предыдущие N раз».
    2. Шаблоны глобусов по умолчанию привязаны к началу и концу. Вот почему я вставил * в начале и в конце шаблона. A * соответствует любому количеству символов. Удалите их, если вы хотите совместить ровно 16 символов.

    Вы можете создать строку из 16 [0-9a-z] с помощью Perl:

     $ pattern="$( perl -e 'print "[0-9a-z]" x 16' )" 

    С помощью bash вы можете выбрать итерацию по всем именам в текущем каталоге, а затем проверить, соответствуют ли имена вашим регулярным выражениям:

     for name in *; do if [[ -f "$name" ]] && [[ "$name" =~ ^[0-9a-z]{16}$ ]]; then echo mv "$name" "$name.txt" fi done 

    Удалите echo если вы знаете, что он поступает правильно.

    Обратите внимание, что я привязал шаблон таким образом, чтобы более длинные имена не совпадали. Я также уверен, что с -f test, что имена, которые мы получаем, на самом деле имеют только обычные файлы.

    Если у вас есть perl-rename (называемый rename в системах на базе Debian, perl-rename на других), вы можете сделать:

     perl-rename -n 's/^[0-9a-z]{16}$/$&.txt/' * 

    Если это делает то, что вы хотите, удалите -n чтобы он фактически переименовал файлы. Синтаксис perl-rename – это команда perl. Здесь мы используем оператор замещения ( s/from/to/ ), который заменит его с. На. В этом случае это ваше регулярное выражение, а to – специальная переменная $& которая означает «все, что было согласовано», плюс расширение .txt .


    Чтобы сделать это с помощью glob оболочки (используйте подход @ Kusalananda или @ Sundeep , это только ради завершения):

     for f in [0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]; do mv -- "$f" "$f".txt done 

    С GNU find :

     find . -regextype posix-extended -regex '.*/[0-9a-z]{16}' -exec mv {} {}".txt" \; 
     L16=$(csh -c 'repeat 16 echo -n "?"') find . -name "$L16" ! -name '*[!0-9a-z]*' -exec sh -c ' mv "$1" "$1.txt" ' {} {} \; 
    Linux и Unix - лучшая ОС в мире.