Linux скрипт или программа для сокращения имен файлов

8

У меня не было большого успеха в поиске Linux-версии namemangler , для которой мне нужно переименовать 1000 файлов, чтобы они были читаемыми в Windows.

Кто-нибудь знает о программе Linux, которая может сделать это?

Если нет, то скрипт может работать, так как мне нужно только переименовать все файлы в папке, скажем, в первые 16 символов. Я подозреваю, что маршрут сценария может стоить идти вниз, но не уверен, с чего начать.

Grimlockz
источник
2
Вы, вероятно, могли бы быстро написать скрипт Python, Perl, Ocaml или Ruby.
Почему вы не можете просто использовать файловую систему vfat, которая допускает длинные имена файлов?
Внуаз
2
Из любопытства, как долго называются имена и что они содержат, что они не распознаются Windows?
Бобби

Ответы:

10

В Debian, Ubuntu и производных, если вы введете man renameв командной строке, вы получите страницу руководства для утилиты переименования, которая позволяет использовать произвольные Perl-подобные команды регулярного выражения для переименования.

Например, это сократит (усечив) все файлы в текущем каталоге до длины пять:

rename 's/^(.{5}).*/$1/' *

Он работает, захватывая первые пять символов, а затем используя их в подстановке, удаляя остальные.

Другой пример - сократить имена файлов (без расширения) до пяти символов, сохранив расширение:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

Он захватывает две группы: первая - первые пять символов, вторая - расширение. Это превратится myCarefullyCraftedDocument.pdfв myCar.pdf.

Предупреждение. Используйте это осторожно, желательно с копией своего каталога или сначала создав резервные копии. Вы были предупреждены!! Как минимум, используйте rename -nсначала, что покажет вам, что будет сделано, на самом деле не делая этого.


источник
1
это избавится от префикса как в PDF? а что будет с файлами с одинаковыми именами при укорочении?
Этот конкретный пример будет, да. Вы можете написать регулярное выражение, чтобы оставить расширение в покое. Я обновлю ответ. Он также защищает от перезаписи уже существующих файлов, поэтому последующее переименование не удастся.
спасибо за вашу помощь в этом - я очень благодарен. У меня есть одна небольшая проблема, если некоторые из PDF-файлов будут переименованы в 5, скажем, что произойдет с PDF-файлами, которые он пытается переименовать с тем же именем? Это способ, которым мы можем просто добавить уникальный номер ко всем этим? см. ниже ename -n 's / ^ (. {5}). * (\ .. *) $ / $ 1 $ 2 /' * Приложения 123114345234525.pdf переименованы в Приложение.pdf Приложения 123114432452352.pdf переименованы в Приложение.pdf
@Grimlockz, я не думаю, что вы можете использовать такой интеллект в самом переименованном регулярном выражении. Что вам может понадобиться, это написать скрипт, чтобы обернуть переименование с помощью такого рода интеллекта, и это лучше задать в виде отдельного вопроса, чтобы вы ответили большему количеству людей, чем просто я.
@Grimlockz Вот почему вы не хотите делать все в регулярных выражениях. Вы будете счастливее и лучше писать скрипт, который использует регулярные выражения.
Спенсер Рэтбун
3

Вы можете переместить конфликтующие файлы в другой каталог:

for i in *
do
    j=${i:0:16}

    if [ -e "$j" ]
    then
        mv "$i" /path/to/rename/later
    else
        mv "$i" "$j"
    fi
done
кэв
источник
1

Вы можете написать скрипт для сокращения имен файлов и удаления символов, которые не нравятся Windows в нескольких строках bash. Предупреждение, непроверенный код, набранный прямо в моем браузере.

shopt -s dotglob extglob
for x in *; do
  y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_}  # change all problematic characters to _
  if [[ $y = .* ]]; then y=_${y#.}; fi        # change dot files to begin with _
  y=${y:0:16}                                 # truncate names
  y=${y,,}                                    # convert to lowercase
  if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
    # The file exists or is a DOS/Windows reserved name.
    # Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
    i=1
    if [[ $y =~ \. ]]; then
      prefix=${y%%.*}; suffix=.${y#*.}
    else
      prefix=$y; suffix=
    fi
    y=${prefix}~$i$suffix
    while [[ -e $y ]]; do
      ((++i))
      y=${prefix}~$i$suffix
    done
  fi
  mv -- "$x" "$y"
done

Если вам нужно перейти в подкаталоги, вызовите скрипт оболочки из find -depth -exec …. Или используйте zsh вместо bash; в zsh **/*(od)рекурсивно расширяется до всех файлов в текущем каталоге, сначала с более глубоко вложенными файлами.

Жиль "ТАК - перестань быть злым"
источник
1

Сценарии оболочки / python / perl для такого рода вещей просто хороши, но кажется, что приложение с графическим интерфейсом будет лучшим для вас, поэтому я бы порекомендовал pyRenamer , который может делать именно то, что вы хотите, среди многих других вещей (простые общие операции через предустановки [избавление от пробелов, усечение имени файла из одной точки в другую], простой поиск / замена, сложное регулярное выражение, предварительный просмотр и т. д.).

Ваш дистрибутив может даже иметь его в своем репозитории программного обеспечения (Fedora делает).

rsaw
источник
0

Некоторые системы не имеют renameкоманды, поэтому в качестве альтернативы ответу paxdiablo, вот как сделать то же самое mv.

for f in *.pdf; do 
    tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
    mv -b ./"$f" ./"$tmp"
done

-bФлаг в движении создает резервную копию файлов , которые будут удалены или перезаписаны. Изменяя шаблон глобуса в цикле for, вы можете настроить, какие файлы он запускает, используя *его для запуска всех файлов.

Спенсер Рэтбун
источник
1
Не нужно использовать echoи канал (может быть очень дорого, если у вас много файлов), используйте вместо этого heredoc или herestring.
Крис Даун
1
@ChrisDown смотрите здесь . Согласно вики-статье , конвейерные процессы разветвляются, но в них ничего не говорится о запуске их в своих оболочках.
Спенсер Рэтбун
1
Например, обратите внимание на разницу между eval 'echo $BASH_SUBSHELL'и eval 'echo $BASH_SUBSHELL' | cat.
Крис Даун
2
Я только что сделал быстрый тест, timeиспользуя цикл с использованием echo $i | sedи другой с использованием sed ... <<<$i, и эта строка заняла около 2/3 времени эха.
Кевин
1
@SpencerRathbun Да. <<запускает здесь <i> документ </ i>, который состоит из нескольких строк и требует разделителей. <<<создает здесь <i> строку </ i>, которая просто принимает одну переменную / строку. Попробуйте это var=abc // cat<<<$var // cat <<$var.
Кевин
0

Если вам нужно поэкспериментировать с переименованием файлов и если в вашей системе установлены библиотеки KDE (или вы не против их добавить), посмотрите krename.

Это позволяет вам делать довольно много простых переименований задач непосредственно с помощью инструментов, а также позволяет использовать регулярные выражения для более сложных ситуаций.

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

Джо
источник
-1
for file in *; do
    mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &
Хайро Бернал
источник