Перейменування файлів у папці на послідовні номери


230

Я хочу перейменувати файли в каталозі на послідовні номери. На основі дати створення файлів.

Для прикладу , sadf.jpgщоб 0001.jpg, wrjr3.jpgщоб 0002.jpgі так далі, кількість провідних нулів в залежності від загальної кількості файлів (немає необхідності в додаткових нулів , а то й потрібно).


Я дивився на stackoverflow.com/questions/880467/… , але не можу дозволити цьому працювати на мене.
Gnutt

1
Linux / Unix не зберігають дату створення.
Призупинено до подальшого повідомлення.

1
лс -1тр | перейменуйте -v 's /.*/ наш $ i; if (! $ i) {$ i = 1;} sprintf ("% 04d.jpg", $ i ++) / e'
maXp

Відповіді:


313

Спробуйте використовувати цикл let, і printfдля прокладки:

a=1
for i in *.jpg; do
  new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
  mv -i -- "$i" "$new"
  let a=a+1
done

використання -iпрапора запобігає автоматичному перезапису існуючих файлів.


4
Ви також printf -v new "%04d.jpg" ${a}можете ввести значення в змінну. І ((a++))працює на збільшення змінної. Крім того, це не робиться під час встановлення дати створення або мінімізації прокладки, що є специфікою, визначеною ОП. Однак слід зазначити, що Linux / Unix не зберігає дату створення.
Призупинено до подальшого повідомлення.

3
Потрібно подвоїти цитати, щоб перетворити телевізор, щоб це працювало в моєму баш-середовищі. mv "$ {i}" "$ {new}"
Gary Thomann

2
Може бути просто Cygwin (хоча його термінальна поведінка значною мірою ідентична звичайним оболонкам Unix), але, схоже, є проблема, коли у назві файлу є пробіли.
Geesh_SO

2
Напевно, також було б бажано використовувати mv -- "$i" "$new"для правильної обробки вихідних імен файлів, які починаються з тире; як це буде, mvспробуємо розібрати такі назви файлів, як колекції прапорів.
Чарльз Даффі

2
Я втратив близько 800 файлів з першого погляду. Я думаю, що -iслід включити у відповідь, і замітку слід переписати відповідно. це буде більш безпечно. :(
KrIsHnA

269

Краса в одну лінію:

ls -v | cat -n | while read n f; do mv -n "$f" "$n.ext"; done 

Ви можете змінити .extз .png, .jpgі так далі


4
легенда :), я використав це на git shell на windows, чудово працює! ^^.
Mr.K

4
Працює чудово. Краса в одну лінію. Я додав ls -tr отримати файли за останній модифікований час.
Ранджіт Сіджі

32
додайте printf так: ls | cat -n | while read n f; do mv "$f" `printf "%04d.extension" $n`; doneмати нульові цифри
Seweryn Niemiec

8
Попередження: Ви можете додати -nкоманду mv, щоб запобігти випадковому перезапису файлів. Виявив це важкий шлях!
Ян Данфорт

4
Складання разом декількох чудових ідей із коментарів до цієї відповіді та інших: ls -1prt | grep -v "/$" | cat -n | while read n f; do mv -n "${f}" "$(printf "%04d" $n).${f#*.}"; done Результати: (1) відсортовано в порядку модифікації, пізніші файли з пізнішими індексами; (2) ігнорує каталоги - і не рекурсивно; (3) індекси колодок; (4) підтримує оригінальне розширення.
Хорхе

63

Мені подобається рішення Гауте за його простоту, але воно має важливий недолік. Працюючи на тисячах файлів, ви можете отримати повідомлення «Аргумент занадто довгий» ( детальніше про це ), а по-друге, сценарій може дійти дуже повільно. У моєму випадку, запустивши його приблизно на 36 000 файлів, сценарій перемістився приблизно. один предмет в секунду! Я не дуже впевнений, чому це відбувається, але правило, яке я отримав від колег, було « findтвій друг» .

find -name '*.jpg' | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command

Для підрахунку елементів та побудови команди використовувався gawk . Зауважте, головну відмінність. За замовчуванням findшукайте файли в поточному каталозі та його підкаталогах, тому не забудьте обмежити пошук лише в поточному каталозі, якщо це необхідно (скористайтеся, man findщоб побачити, як).


7
Я змінив, щоб використовувати номер рядка NRдля коротшої команди. gawk '{ printf "mv %s %04d.jpg\n", $0, NR }'
Apiwat Chantawibul

12
Тут масові вразливі місця безпеки. Подумайте, чи є у вас файл з іменем $(rm -rf /).jpg.
Чарльз Даффі

Дякую за те, що вказав на Чарльза. Чи можете ви запропонувати безпечне рішення?
beibei2

2
розбивається у випадку, якщо ім'я файлу має пробіли. Використовуйте лапки навколо назви вихідного файлу. printf "mv \"% s \ "% 04d.jpg \ n", $ 0, a ++
baskin

1
forЦикл не приймає 1 секунду на файл, строго кажучи. Потрібно багато часу, щоб отримати 36000 імен файлів з файлової системи, а потім циклічно обробляти їх. У багатьох файлових системах є проблеми з великими каталогами, незалежно від того, які точні команди ви виконуєте; але, як правило, findце буде швидше, ніж підстановочний символ оболонки, оскільки він повинен отримати та сортувати список відповідних файлів.
трійчатка

30

з командою "перейменувати"

rename -N 0001 -X 's/.*/$N/' *.jpg

або

rename -N 0001 's/.*/$N.jpg/' *.jpg

32
Мій rename(Linux Mint 13) не має -Nможливості.
Лука H

Я можу висловитись лише за згадку про команду перейменування, я ніколи про неї не чув
user907860

8
Мені цікаво дізнатися, де можна отримати команду перейменування з опцією -N. У мого Ubuntu 14.04 його немає.
Стефан Геннінгсен

1
Я люблю renameкоманду, але про це ніколи не знав -N! Дякую!
Dan Lecocq

1
Існують щонайменше три різні інструменти, відомі якrename . Посилання, розміщене @Bostrot, є ще одним інструментом перейменування, і, схоже, @RomanRhrnNesterov використовував цей. ¶ Для всіх користувачів renameПедера Страйя та Ларрі Уолла (пакет perl-renameдля арки Linux та пакунок renameна debian / ubuntu): Ви можете визначити $Nсебе:perl-rename '$N=sprintf("%04d",++$N); s/.*/$N.jpg/' *.jpg
Socowi

30

використання рішення Pero на OSX вимагало певних змін. Я використав:

find . -name '*.jpg' \
| awk 'BEGIN{ a=0 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' \
| bash

зауважте: зворотні риски є для продовження лінії

редагувати 20 липня 2015 року: включений відгук @ klaustopher для цитування \"%s\"аргументу mvкоманди для підтримки назви файлів з пробілами.


3
Як і рішення Перо, тут є вразливості безпеки. Подумайте, чи є у вас файл з іменем $(rm -rf /).jpg.
Чарльз Даффі

Дякую, це працює. Але вам слід навести перший аргумент mv. Якщо у вас є файл з ім'ям, тобто some thing.jpgваш сценарій не працює. Це те, що я використав:find . -name '*.jpg' | awk 'BEGIN{ a=0 }{ printf "mv \"%s"\ wallpaper-%04d.jpg\n", $0, a++ }' | bash
klaustopher

я, мабуть, використовував -maxdepth 1би лише роботу в jpgs у поточному каталозі, так як краще бути в безпеці, ніж шкодувати.
Пітер Пергач

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

ви можете використовувати ls -1 *.jpgзамість знаходження, інакше це не буде відсортовано. Або додайте |sort|перед awk
JPT

28

Дуже простий bash один вкладиш, який зберігає оригінальні розширення, додає провідні нулі, а також працює в OSX:

num=0; for i in *; do mv "$i" "$(printf '%04d' $num).${i#*.}"; ((num++)); done

Спрощена версія http://ubuntuforums.org/showthread.php?t=1355021


Саме те, що я шукав. Мені подобається, що ви можете встановити індекс старту.
Джек Віал

2
Зверніть увагу: це не збереже початковий порядок файлів.
Рой Шилкрот

@RoyShilkrot Що ви маєте на увазі під " не зберегти початковий порядок "? Глобуси в bash та інших позиційних оболонках розширюються в упорядкованому порядку відповідно до локальної системи. Звичайно, це не сортували 9.extраніше 11.ext, але інші інструменти (як ls) теж не роблять цього.
Socowi

11

Щоб працювати у будь-яких ситуаціях, поставте \ "для файлів, які мають пробіл у назві

find . -name '*.jpg' | gawk 'BEGIN{ a=1 }{ printf "mv \"%s\" %04d.jpg\n", $0, a++ }' | bash

3
Фактично не охоплює всіх ситуацій. Ім'я файлу, що містить буквальні лапки, може тривіально вийти з огляду на те, що ви використовуєте подвійні лапки, а не окремі цитати, такі розширення як $(rm -rf /)і раніше шануються.
Чарльз Даффі

11

Якщо ваш renameне підтримує -N, ви можете зробити щось подібне:

ls -1 -c | xargs rename -n 's/.*/our $i; sprintf("%04d.jpg", $i++)/e'

Редагувати Для початку із заданого числа ви можете використовувати (дещо некрасивий) код нижче, просто замініть 123 на потрібний номер:

ls -1 -c | xargs rename -n 's/.*/our $i; if(!$i) { $i=123; } sprintf("%04d.jpg", $i++)/e'

У цьому списку перераховані файли за часом створення (найновіше, спочатку додайте -rдо ls для зворотного сортування), після чого надсилається цей список файлів для перейменування. Перейменування використовує код perl в регулярному виразі для форматування та збільшення лічильника.

Однак якщо ви маєте справу з зображеннями JPEG з інформацією EXIF, рекомендую exiftool

Це з документації exiftool у розділі "Перейменування прикладів"

   exiftool '-FileName<CreateDate' -d %Y%m%d_%H%M%S%%-c.%%e dir

   Rename all images in "dir" according to the "CreateDate" date and time, adding a copy number with leading '-' if the file already exists ("%-c"), and
   preserving the original file extension (%e).  Note the extra '%' necessary to escape the filename codes (%c and %e) in the date format string.

Як я можу почати з певного числа, використовуючи rename?
січня

6

На OSX встановіть сценарій перейменування з Homebrew:

brew install rename

Тоді ви можете зробити це справді смішно легко:

rename -e 's/.*/$N.jpg/' *.jpg

Або додати приємний префікс:

rename -e 's/.*/photo-$N.jpg/' *.jpg

3
Це чудовий сценарій, і це залежить лише від Perl. brew працює лише на Mac, але ви можете схопити його з github ( github.com/ap/rename ) і використовувати його в Linux або Windows.
Тім Даннер

3
це не працює для мене. Я отримавGlobal symbol "$N" requires explicit package name (did you forget to declare "my $N"?) at (user-supplied code).
Ентоні Чанг,

Як користувач Mac, я радий повідомити, що додаток для перейменування, пов’язаний з @TimDanner, є супер портативним, це було так само просто, як завантаження архіву Zip, перекидання утиліти перейменування в каталог, на який встановлений мій шлях баш-профілю. , і це працює прямо з коробки. Я здивований, що це не доступно для MacPorts. Я вважаю це настільки дивним, що у мене є сторінка BSD для Rename (2), але при запуску перейменування вона скаже, що команди немає. Піди розберися.
adamlogan

2

Виконайте команду Перейменуйте всі файли в послідовність, а також розширення з малих літер:

rename --counter-format 000001 --lower-case --keep-extension --expr='$_ = "$N" if @EXT' *

1

У мене був подібний випуск і з цієї причини написав сценарій оболонки. Я вирішив опублікувати його незалежно від того, що вже було розміщено багато хороших відповідей, оскільки я думаю, що це може бути корисним для когось. Сміливо вдосконалюйте його!

числити

@Gnutt Потрібної поведінки можна досягти, ввівши наступне:

./numerate.sh -d <path to directory> -o modtime -L 4 -b <startnumber> -r

Якщо опція -rвідсутня, переймування буде лише імітуватися (має бути корисним для тестування).

У розділі L описується довжина цільового числа (яке буде заповнено провідними нулями), також можна додати префікс / суфікс з параметрами -p <prefix> -s <suffix>.

Якщо хтось хоче, щоб файли були сортовані чисельно, перш ніж їх нумерувати, просто видаліть цю -o modtimeопцію.



1

Припустимо, ці файли містяться в каталозі, переліченому в порядку створення, причому перший є найстарішим:

a.jpg
b.JPG
c.jpeg
d.tar.gz
e

то ls -1crвиводить саме список, наведений вище. Потім ви можете використовувати rename:

ls -1cr | xargs rename -n 's/^[^\.]*(\..*)?$/our $i; sprintf("%03d$1", $i++)/e'

який виводить

rename(a.jpg, 000.jpg)
rename(b.JPG, 001.JPG)
rename(c.jpeg, 002.jpeg)
rename(d.tar.gz, 003.tar.gz)
Use of uninitialized value $1 in concatenation (.) or string at (eval 4) line 1.
rename(e, 004)

Попередження «використання неініціалізованого значення […]» відображається для файлів без розширення; ви можете проігнорувати це.

Видаліть -nіз renameкоманди, щоб фактично застосувати перейменування.

Ця відповідь натхненна відповіддю Луки з квітня 2014 року . Він ігнорує вимогу Гнута встановити кількість провідних нулів залежно від загальної кількості файлів.


Це була найкорисніша відповідь тут для мене, здебільшого тому, що я хотів сухий запуск операційного апарату, перш ніж він запустився, а також тому, що я міг настроїти замовлення, змінивши на ls -1tUчас створення. Це також було потрібно renameвстановити, чого я не мав.
антоні

1

Знову використовуйте рішення Перо з невеликими модифікаціями, тому що findбуде проходити дерево каталогів, щоб елементи замовлення зберігалися у записах каталогу. Це (в основному) буде послідовно від запуску до запуску на одній машині і по суті буде "порядком створення файлів / директорій", якщо не було видалених.

Однак у деяких випадках потрібно отримати певний логічний порядок, скажімо, по імені, який використовується в цьому прикладі.

find -name '*.jpg' | sort -n | # find jpegs
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command 

3
НЕ використовуйте це. Перенаправлення на башти, як це, є великим ризиком для безпеки. Що робити, якщо одна з назв файлу має форму blahblah; rm -r * blahblah.jpg?
xhienne

1

Відсортовано за часом, обмежене jpg, провідними нулями та базовою назвою (якщо ви, ймовірно, хочете)

ls -t *.jpg | cat -n |                                           \
while read n f; do mv "$f" "$(printf thumb_%04d.jpg $n)"; done

(все в одному рядку, без цього \)


У грандіозній схемі речей багато відповідей на цій сторінці жахливі, тому, можливо, це не особливо заслуговує наголошення. Я, мабуть, вагаюсь, щоб проголосувати все, що використовується lsв сценарії.
трійчатка

Цю відповідь я зберігаю з негативної сторони, оскільки, мабуть, неміцна, вона працювала для конкретного випадку, який я мав.
Віль

1
ls -1tr | rename -vn 's/.*/our $i;if(!$i){$i=1;} sprintf("%04d.jpg", $i++)/e'

перейменувати -vn - видалити n для вимкнення тестового режиму

{$ i = 1;} - номер запуску управління

"% 04d.jpg" - контрольний відлік нуля 04 та встановлення розширення виводу .jpg


Поскарживши цю відповідь, оскільки вона використовує лише нове ім’я. Моя справа використання полягала в заміні перших двох цифр файлів цифрами, починаючи з 01:rename -v -n 's/../our $i;if(!$i){$i=1;} sprintf("%02d", $i++)/e' *
заднім числом

1

Для мене це поєднання відповідей спрацювало чудово:

ls -v | gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | bash
  • ls -v допомагає впорядкувати 1 10 9 правильно: 1 9 10 порядку, уникаючи проблем із розширенням назви файлів у форматі jpg JPG jpeg
  • gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }'перечисляє 4 символи та провідні нулі. Уникаючи mv, я випадково не намагаюся перезаписати все, що є, вже випадково маючи однакову кількість.
  • bash виконує

Будьте в курсі того, що сказав @xhienne, передача невідомого вмісту на башти - це ризик безпеки. Але це було не так для мене, коли я використовував свої відскановані фотографії.


0

Ви також можете використовувати ls

ls *.JPG| awk 'BEGIN{ a=0 }{ printf "mv %s gopro_%04d.jpg\n", $0, a++ }' | bash

5
Дивіться mywiki.wooledge.org/ParsingLs , а також описи вразливих місць безпеки інших, аналогічно розбитих рішень.
Чарльз Даффі

1
НЕ використовуйте це. Перенаправлення на башти, як це, є великим ризиком для безпеки. Що робити, якщо одна з назв файлу має форму blahblah; rm -r * blahblah.JPG?
xhienne

0

Більшість інших рішень замінить існуючі файли, вже названі числом. Особливо це проблема, якщо запустити сценарій, додати більше файлів, а потім знову запустити сценарій.

Цей сценарій спочатку перейменовує наявні числові файли:

#!/usr/bin/perl

use strict;
use warnings;

use File::Temp qw/tempfile/;

my $dir = $ARGV[0]
    or die "Please specify directory as first argument";

opendir(my $dh, $dir) or die "can't opendir $dir: $!";

# First rename any files that are already numeric
while (my @files = grep { /^[0-9]+(\..*)?$/ } readdir($dh))
{
    for my $old (@files) {
        my $ext = $old =~ /(\.[^.]+)$/ ? $1 : '';
        my ($fh, $new) = tempfile(DIR => $dir, SUFFIX => $ext);
        close $fh;
        rename "$dir/$old", $new;
    }
}

rewinddir $dh;
my $i;
while (my $file = readdir($dh))
{
    next if $file =~ /\A\.\.?\z/;
    my $ext = $file =~ /(\.[^.]+)$/ ? $1 : '';
    rename "$dir/$file", sprintf("%s/%04d%s", $dir, ++$i, $ext); 
}

0

Цей oneliner перераховує всі файли в поточному каталозі, сортує за тимчасовою міткою створення у зворотному порядку (означає, що найстаріший файл знаходиться на початку) та автоматично перейменовується з остаточними нулями відповідно до кількості файлів. Розширення файлу буде збережено.

Зазвичай у мене є лише одна папка з роками для фотографій і фільмів мобільних телефонів. Застосовуючи цю команду, мої фотографії та фільми готові потім до слайд-шоу у правильному порядку на телевізорі чи архівуванні.

Майте на увазі, що якщо у вас зіткнення імен файлів, ви втрачаєте файли. Тому спочатку перейменуйте щось на зразок дивного типу, temp001.jpgа потім виконайте остаточне ім'я файлу.

DIGITS=$(ls | wc -l | xargs | wc -c | xargs); ls -tcr | cat -n | while read n f; do mv "$f" "$(printf "%0${DIGITS}d" $n).${f##*.}"; done

1
Бігати lsне один раз, а двічі виглядає так, що цього краще уникати, але я не вивчав його жодної глибини.
трійчатка

1. Якщо я пропоную навмисне онлайнер, то чому ви його змінюєте згодом? Багато користувачів, як я, вважають за краще скопіювати та вставити oneliner, щоб виконати завдання. Для інших, хто вважає за краще копіювати рядок за рядком, у цій темі є інші відповіді. 2. Оригінальним питанням було "кількість провідних нулів залежно від загальної кількості файлів", і це робиться першим ls, тому два з них потрібні. 3. Такі команди - це поодинокі знімки, і їх не передбачають включати в сценарії, тому є причина, чому люди віддають перевагу однолінійкам
Flavio Aiello

1
Вибачте, не зрозумів, що ви вважаєте це важливим. Для мене вміння читати код сильно перетворює здатність копіювати / вставляти його як єдиний рядок. Я не знайшов середовища, де у Bash виникли проблеми з пастою, яка охоплює кілька рядків, але я, можливо, щось не помічаю.
трійчатка

0

Ось що для мене спрацювало.
Я використав команду перейменування, так що якщо будь-який файл містить пробіли в його імені, тоді команда mv не плутається між пробілами та фактичним файлом.

Тут я замінив пробіли, '' у назві файлу на '_' для всіх jpg-файлів
#! / бін / баш
перейменувати 'y / / _ /' * jpg #заміщення пробілів на _
нехай x = 0;
для я в * .jpg; робити
    нехай x = (x + 1)
    mv $ i $ x.jpg
зроблено

Встановіть перейменування на Linux (ubuntu), "sudo apt install rename"
rishang bhavsar

0

На сьогоднішній день існує можливість після вибору декількох файлів для перейменування (я бачив у thunar file manager).

  1. виберіть кілька файлів
  2. перевірити варіанти
  3. вибрати перейменувати

Підкажіть, що всі файли у цьому конкретному режимі просто перевірте розділ категорії


-1

Цей скрипт буде сортувати файли за датою створення на базі Mac OS. Я використовую його для масового перейменування відео. Просто змініть розширення та першу частину назви.

ls -trU *.mp4| awk 'BEGIN{ a=0 }{ printf "mv %s lecture_%03d.mp4\n", $0, a++ }' | bash

1
НЕ використовуйте це. Перенаправлення на башти, як це, є великим ризиком для безпеки. Що робити, якщо одна з назв файлу має форму blahblah; rm -r * blahblah.mp4?
xhienne

-1

Ось ще одне рішення з командою "перейменувати":

find -name 'access.log.*.gz' | sort -Vr | rename 's/(\d+)/$1+1/ge'

Для відновлення провідних нулів:rename 's/(\d+)/sprintf("%04d",$1)+1/ge'
Каміль Ґудесюн,

Не працює, як очікувалося, для папки з файлами з такими іменами: DSC_3451.JPG, DSC_3452.JPG і т.д. find -name '* .JPG' | сортувати -Vr | перейменувати 's / (\ d +) / $ 1 + 1 / ge' нічого не змінює
Тіберіу C.

-2

Відповідь Перо дістала мене тут :)

Я хотів перейменовувати файли відносно часу, оскільки глядачі зображень не відображали зображення в порядку часу.

ls -tr *.jpg | # list jpegs relative to time
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | # build mv command
bash # run that command

2
НЕ використовуйте це. Перенаправлення на башти, як це, є великим ризиком для безпеки. Що робити, якщо одна з назв файлу має форму blahblah; rm -r * blahblah.jpg? Просто крайній приклад.
xhienne


-3

Щоб перенумерувати 6000 файлів у одній папці, ви можете скористатися параметром «Перейменувати» програми ACDsee.

Для визначення префікса використовуйте цей формат: ####"*"

Потім встановіть початковий номер і натисніть Перейменувати, і програма перейменує всі 6000 файлів з послідовними номерами.


1
ОП просить набір команд в Unix Bourne Shell. Ви пропонуєте комерційний продукт, який працює лише в середовищі Windows.
xhienne
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.