Linux переименовывает файлы в верхний регистр

20

У меня есть большое количество файлов в формате x00000.jpg , X00000.jpg и xx00000.jpg .

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

    
задан Jay 27.11.2013 в 22:39
источник
  • Хотите, чтобы переименованный x00000.jpg заменил оригинальный X00000.jpg? –  chepner 27.11.2013 в 22:48
  • Linux имеет тенденцию напоминать имена файлов в нижнем регистре. Почему вы хотите все в верхнем регистре? –  Keith Thompson 27.11.2013 в 22:52
  • честно, это было либо верхним, либо нижним, и я выбрал верх в случайном порядке. Я использую изображения как часть URL-адреса, с которой я связываюсь с идентификатором, предоставленным в фиде данных. идентификатор совпадает с именем изображения. К сожалению, данные фида и данные файла изображения не соответствуют случайным образом. –  Jay 27.11.2013 в 22:55

7 ответов

21
for f in * ; do mv -- "$f" "$(tr [:lower:] [:upper:] <<< "$f")" ; done
    
ответ дан damienfrancois 27.11.2013 в 22:49
  • Но почему подоболочка, вилка и здесь-строка? «$ {f ^^}» было бы достаточно. –  gniourf_gniourf 27.11.2013 в 22:58
  • Аргументы в tr также должны быть указаны. Рассмотрим touch l u; tr [: lower:] [: upper:] <<< «привет мир» –  that other guy 27.11.2013 в 23:21
  • Будет ли это не переименовывать x00000.jpg в X00000.JPG, хотя OP, похоже, хочет X00000.jpg –  anubhava 27.11.2013 в 23:26
  • Передача опции -s в tr выглядит как ошибка, которая может уничтожить данные. –  user2719058 28.11.2013 в 02:55
  • Следует также отметить, что tr [: lower:] [: upper:] не обрабатывает многобайтовые символы (пока). То же самое относится к предложенному $ {f ^^} в bash (зафиксированному в bash 4.3, который еще не выпущен). sed работает, по крайней мере, на моей машине. –  user2719058 01.12.2013 в 00:41
12

Вы не можете переименовывать файлы только из Bash, потому что Bash не имеет встроенной команды для переименования файлов. Для этого вы должны использовать хотя бы одну внешнюю команду.

Если Perl разрешен:

perl -e 'for(@ARGV){rename$_,uc}' *.jpg

Если Python разрешен:

python -c 'import os, sys; [os.rename(a, a.upper()) for a in sys.argv[1:]]' *.jpg

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

Если доступны AWK, ls и mv :

# Insecure if the filenames contain an apostrophe or newline!
eval "$(ls -- *.jpg | awk '{print"mv -- \x27"$0"\x27 \x27"toupper($0)"\x27"}')"

Если у вас много файлов, приведенные выше решения не работают, поскольку *.jpg расширяется до слишком длинного списка аргументов (ошибка: Список аргументов слишком длинный ).

Если разрешено tr и mv , см. ответ Дэмиенфрансуа.

Если mv разрешен:

for file in *; do mv -- "$file" "${file^^}"; done

Обратите внимание, что в конце они переименовывают .jpg в .JPG , но вы можете изменить их, чтобы избежать этого.

    
ответ дан pts 27.11.2013 в 22:48
  • Осторожно, команда Perl также сделает расширение верхнего регистра, так что файлы pdf / zip станут PDF / ZIP –  Parik Tiwari 18.06.2015 в 01:32
  • @ParikTiwari: Это верно для всех команд в этом ответе, а также для большинства команд в других ответах. –  pts 19.06.2015 в 09:51
8

Оболочка bash имеет синтаксис для перевода имени переменной в прописные буквы.

for file in * ; do      # or *.jpg, or x*.jpg, or whatever
    mv $file ${file^^}
done

Я думаю, что это может быть довольно новая функция, поэтому сначала убедитесь, что ваша версия bash реализует ее. Чтобы избежать ошибок, попробуйте один раз заменить mv на echo mv , просто чтобы убедиться, что он будет делать то, что вы хотите.

Документация по этой функции: здесь или введите info bash и искать "верхний".

Вероятно, вам следует решить, что делать, если целевой файл уже существует (например, если уже существуют x00000.jpg и X00000.JPG ), если вы не уверены, что это не проблема. Чтобы обнаружить такие конфликты имен, вы можете попробовать:

ls *.txt | tr '[a-z]' '[A-Z]' | sort | uniq -c | sort -n

и найдите строки, не начинающиеся с 1 .

    
ответ дан Keith Thompson 27.11.2013 в 22:50
  • Это работает для меня, но я хотел, чтобы расширение файла также изменялось на все символы верхнего регистра. FYI, я по-прежнему (позорно) качаю версию 4.1.5 (1) -release (x86_64-pc-linux-gnu) bash ... –  Digger 14.01.2018 в 19:34
  • @ Digger: Это именно то, что он делает. $ {file ^^} обрабатывает $ file как одну строку. Расширение является частью имени файла. Но спросите себя, почему вы хотите это сделать. Linux поддерживает верхний, нижний и смешанный фреймы, но строчный регистр является обычным. –  Keith Thompson 15.01.2018 в 02:00
7

Объединение предыдущих ответов может дать:

for file in * ; do            # or *.jpg, or x*.jpg, or whatever
   basename=$(tr '[:lower:]' '[:upper:]' <<< "${file%.*}")
   newname="$basename.${file#*.}"
   mv "$file" "$newname"
done
    
ответ дан Wiley 03.11.2014 в 14:10
  • это работает и не испортит дела расширения файла, то есть он остается .jpg не .JPG –  ski_squaw 02.10.2015 в 18:33
3

Использование tr:

f="x00000.jpg"
n="${f%.*}"
n=$(tr '[:lower:]' '[:upper:]' <<< "$n")
f="$n.${f#*.}"
echo "$f"

ВЫВОД:

X00000.jpg
    
ответ дан anubhava 27.11.2013 в 22:40
  • Классы символов, такие как [a-z], зависят от языка и могут использовать скрытые ошибки. Кроме того, ваше решение не обрабатывает многобайтовые символы. –  user2719058 01.12.2013 в 00:47
  • Да, это справедливая точка, хотя я не видел многобайтового требования в вопросе OP, но я редактировал. –  anubhava 01.12.2013 в 05:30
  • Многобайтные имена файлов не были упомянуты OP, но большинство имен файлов создаются людьми, поэтому это должно решаться решением. Тем не менее, к сожалению, tr '[: lower:]' ... не обрабатывает многобайтовые символы. Это действительно плохо. :( (О, и вам лучше процитировать [: lower:] здесь, потому что иначе оболочка может расширять ее до имени файла. :) –  user2719058 01.12.2013 в 15:02
2

rename

Используйте команду rename для переименования нескольких файлов. Я думаю, что это самый простой способ. Чтобы перевести строчные имена в верхние, вы должны использовать:

rename 'y/a-z/A-Z/' *

Ссылка

ответ дан Pablo Bianchi 11.08.2017 в 20:38
0

Если вам нужно только переименовать файлы / каталоги, вы можете использовать rnm :

rnm -rs '/./\C/g' -fo -dp -1 *

Пояснение:

  1. -rs : заменить строку. /./\C/g заменяет все совпадения . (регулярное выражение) на заглавные.
  2. -fo : режим только для файлов
  3. -dp : глубина каталога (-1 означает неограниченный).

Дополнительные примеры можно найти здесь .

    
ответ дан Jahid 07.05.2016 в 10:33