Як перейменувати файли та замінити символи?


11

У мене є група файлів, які мають :(двокрапку) в імені. Мені потрібно замінити :з -(тире).

Чи є простий спосіб зробити це в сценарії?

Зразок імені файлу: 2013-10-11:11:52:08_055456663_045585_.txt

Відповіді:


17

Простий 1-лайнер повинен зробити (передбачає сумісність з Posix sh):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Пояснення:

  • for ... in ...; do ...; done- це петля

  • *:* збігається з усіма файлами та каталогами в поточному каталозі, які мають :своє ім'я

  • f призначається по черзі кожному такому імені файлу в циклі

  • mvперейменовує свій перший аргумент на другий; -v(багатослівний) просить надрукувати те, що робить; ця опція специфічна для GNU-утилітів , тому вона доступна в Linux, але не в Solaris

  • $(...) виконує код у підколонці та замінює вихід

  • echo друкує свій аргумент на стандартний висновок

  • tr читає стандартний вихід і переводить символи відповідно до наданої карти

Якщо ви використовуєте bash , ви можете уникнути нересту додаткової оболонки ( $()) з підпроцесами ( tr), замінивши $(...)на ${f//:/-}.


+1 за просту робочу відповідь, хоча це може зробити трохи більше пояснень. Наприклад, for f inцикл ... - це цикл, який повторює всі файли в поточному каталозі, де вони повинні відповідати *:*. (Що відбувається з дрирами, які відповідають?). Команда переміщення - це стара назва нового переміщення, де нове ім’я генерується шляхом виконання оболонки з $( subshell here ). Що робить тр, ...
Геннес

@Hennes: це привілейований користувач - мені дійсно потрібно йти в ці види деталей? Ну добре, ось ви йдете ...
sds

Ні. Якби була реальна потреба, тоді я не мав би +1. І я розумію, що це робить. Я думаю, що це приємно для багатьох інших читачів.
Hennes

2
Ви можете замінити $(echo "$f" | tr ':' '-')з "${f//:/-}"і уникнути подоболочкі, труби і зовнішнього виклику програми. Я думаю, що це башизм, але так. Дивіться тут .
evilsoup

@evilsoup Дійсно; це не має великої різниці для невеликих наборів даних (і це може сприяти читабельності), але ви будете здивовані, наскільки швидко щось подібне додається. Я нещодавно покусав цим; переписування сценарію таким чином, що дві прості команди рядок погладжування більше не були потрібні легко скоротити час виконання на 90% або більше, що на великий набір даних був переведений на кілька хвилин часу виконання стандартної дати.
CVn

6

Як сказано в іншому мною, цей renameінструмент може зробити для вас трюк. Вам просто потрібно ввести rename s/:/-/ <files to rename> Це замінює кожну двокрапку тире в усіх файлах, які ви називаєте в кінці, тобто2013-10-*

Ось посилання на інший мій пост


1

Я впевнений, що UNIX Pro може це зробити з bash, але ось моя швидка і брудна версія з рубіном.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

встановіть path_to_files до шляху до ваших неправильно названих файлів. збережіть наведений вище код у файлі під назвою rename.rb:

username@machinename$ ruby rename.rb

@sds дає набагато кращу відповідь. Чи слід видалити свою відповідь? Я новачок у stackoverflow.
шупру

1
Ні; вона все ще має значну цінність. :)
Blacklight Shining

2
Однак є кілька основних недоліків цієї відповіді, які можуть бути актуальними і про них, безумовно, варто знати. (Це все ще може бути корисним, але попереджувальний емпатор і все таке.) Перш за все, схоже, він погано зламається, коли в них зустрічаються назви файлів з пробілом (не лише класичним випадком відмови). Крім того, навіть якщо це не білий пробіл, вам слід вказати ім'я файлу у виклику оболонки, щоб захистити будь-які інші спеціальні символи в іменах файлів від обробки оболонкою (хоча я не знаю точно, як працює оператор backtick Ruby ).
CVn

1

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

  1. Зберігайте зразок імені файлу , який ви орієнтуєтеся в якості змінної: p="201*".
  2. Зберігайте старе ім'я файлу , який ви хочете перейменувати: old_name=$(ls | grep $p).
  3. Збережіть нове ім’я файлу з необхідними символьними замінами:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Прибирання бонусів :
  a. Якщо для рівномірності ви хочете замінити тире (-) разом з колонами (:) на підкреслення (_), ви можете зробити це:

    new_name=$(ls | grep $p | tr ':-' '_');

  б. Якщо ви хочете, щоб останній підкреслення (безпосередньо перед .txt) пройшов також, встановіть new_nameзмінну як:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Тепер перейменуйте свій файл за потребою: mv $old_name $new_name

         Примітка: mvне вдасться, якщо будь-яке з назв файлів в операції з перейменування містить spacesв ньому. У цьому випадку оберніть відповідні змінні в лапки, як-от:
mv "$old_name" $new_name АБО mv $old_name "$new_name" АБО mv "$old_name" "$new_name"


Однолінійні

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name

0

з використанням перейменування :

$ renamer --find ":" --replace "-" *

Я думаю, що встановити повне середовище node.js для перейменування файлів - це занадто багато. renameце інструмент, який встановлено на багатьох дистрибутивах Linux. Але я думаю, для Windows цей інструмент може бути чудовим.
noggerl

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