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

19

У меня есть большое количество файлов в формате 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 ответов

20
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
11

Вы не можете переименовывать файлы только из 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"
for file in *; do mv -- "$file" "${file^^}"; done
"\x27 \x27"toupper(%pre%)"\x27"}')"

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

Если tr и mv разрешены, см. ответ damienfrancois.

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

%pre%

Обратите внимание, что в конце они переименовывают .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 есть синтаксис для преобразования имени переменной в all-caps.

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
5

Объединяя предыдущие ответы, можно получить:

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 заменяет все совпадения . (regex) на верхний регистр.
  2. -fo : режим только файла
  3. -dp : глубина директории (-1 означает неограниченную).

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

    
ответ дан Jahid 07.05.2016 в 10:33
источник