Переименование большого количества файлов изображений с помощью bash

Я знаю, что часть после pub ABCDE/ является открытым ключом, а часть после sec ABCDE/ является закрытым ключом.

Вы ошибаетесь в поле идентификации алгоритма с идентификатором ключа.

sec   ABCDE/XXXXXXXL 2016-06-09
uid                  My Name (comment) <example@email.com>
sub   ABCDE/XXXXXXXM 2016-06-09
sub   ABCDE/XXXXXXXN 2016-06-10

Поле, которое вы скрывали через ABCDE, никогда не может быть ABCDE. Это поле содержит идентификатор алгоритма и ключа, например R4096 для 4096-битного ключа RSA. Ожидается, что она будет содержать ту же информацию для одного и того же алгоритма и размера ключа. [F7] обозначает 1024 битный ключ DSA, и так далее

The (кратковременно) ID является частью за косой чертой /. - и, глядя на вопрос, это уже, кажется, отличается, так или иначе .

Я знаю, что часть после того, как pub ABCDE/ является открытым ключом, а часть после того, как sec ABCDE/ является закрытым ключом.

Как я могу получить отдельные открытые и закрытые ключи?

16
задан 22 May 2018 в 13:11

16 ответов

Я вижу, что никто не пригласил моего лучшего друга sed на вечеринку :). Следующий цикл for выполнит вашу задачу:

for i in sb_606_HBO_DPM*; do mv "$i" "$(echo $i | sed 's/HBO_DPM/dpm/')"; done

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

3
ответ дан 17 July 2018 в 13:56

Вы можете написать небольшой скрипт python, например:

import os for file in os.listdir("."): os.rename(file, file.replace("HBO_DPM", "dpm"))

Сохранить это как текстовый файл как rename.py в папке, в которой находятся файлы, а затем с помощью терминала в этой папке :

python rename.py
6
ответ дан 17 July 2018 в 13:56

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

rename -v 'y/sb_606_HBO_DPM_/sb_606_dpm_/' *
-1
ответ дан 17 July 2018 в 13:56

В зависимости от вида переименования, которое вы предполагаете, использование vidir с редактированием нескольких строк может быть удовлетворительным. В вашем конкретном случае вы можете выбрать все строки в текстовом редакторе и удалить часть имен файлов «HBO» в несколько нажатий клавиш.

1
ответ дан 17 July 2018 в 13:56

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

mmv

Я бы использовал команду mmv из пакета с тем же именем:

mmv '*HBO_DPM*' '#1dpm#2'

Обратите внимание, что аргументы передаются как строки, поэтому расширение glob не происходит в оболочке. Команда получает ровно два аргумента, а затем находит соответствующие файлы внутри, без жестких ограничений на количество файлов. Также обратите внимание, что в приведенной выше команде предполагается, что все файлы, соответствующие первому шару, должны быть переименованы. Конечно, вы можете быть более конкретными:

mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'

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

mmv 'sb_606_HBO_DPM_0089*' 'sb_606_dpm_0089#1' # 0089000-0089999 mmv 'sb_606_HBO_DPM_009*' 'sb_606_dpm_009#1' # 0090000-0099999 mmv 'sb_606_HBO_DPM_01[0-5]*' 'sb_606_dpm_01#1#2' # 0100000-0159999 mmv 'sb_606_HBO_DPM_016[0-2]*' 'sb_606_dpm_016#1#2' # 0160000-0162999 mmv 'sb_606_HBO_DPM_01630[01]?' 'sb_606_dpm_01630#1#2' # 0163000-0163019 mmv 'sb_606_HBO_DPM_016302[0-2]' 'sb_606_dpm_016302#1' # 0163020-0163022

цикл над номерами

Если вы хотите избежать установки чего-либо или вам нужно выбирать по диапазону номеров, избегая соответствует этому диапазону, и вы готовы ждать 74,023 командных вызовов, вы можете использовать простой цикл bash:

for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done

Это работает особенно хорошо, так как в последовательности нет пробелов. В противном случае вам может потребоваться проверить, существует ли исходный файл.

for i in {0089000..0163022}; do test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i done

Обратите внимание, что в отличие от for ((i=89000; i<=163022; ++i)) расширение скобки обрабатывает ведущие нули, поскольку несколько выпусков Bash пару лет назад. На самом деле это изменение, которое я запросил, поэтому я рад видеть его варианты использования.

Дальнейшее чтение: mmv command на информационных страницах Bash, особенно часть {x..y[..incr]} .

loop over files

Другим вариантом будет цикл над подходящим glob, а не просто цикл по целочисленному диапазону, о котором идет речь. Что-то вроде этого:

for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done

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

Дальнейшее чтение: Расширение параметра оболочки на информационных страницах Bash, в том числе документация ${parameter/pattern/string}.

Если вы хотите ограничить диапазон номеров тем, который вы предоставили, вы можете добавить проверьте это:

for i in sb_606_HBO_DPM_+([0-9]); do if [[ "${i##*_*(0)}" -ge 89000 ]] && [[ "${i##*_*(0)}" -le 163022 ]]; then mv "$i" "${i/HBO_DPM/dpm}" fi done

Здесь ${i##pattern} удаляет самый длинный префикс, соответствующий pattern из $i. Этот самый длинный префикс определяется как что-либо, затем подчеркивание, затем нуль или более нулей. Последний записан как *(0), который является расширенным расширением Shell Parameter Expansion , который зависит от установленного пакета с тем же именем . Удаление начальных нулей важно для обработки числа в качестве базы 10, а не базы 8. Параметр +([0-9]) в аргументе цикла представляет собой еще один расширенный глобус, соответствующий одной или нескольким цифрам, на всякий случай, если у вас есть файлы, которые начинаются с того же самого, но не конец в числе.

11
ответ дан 17 July 2018 в 13:56

Один из способов обойти предел ARG_MAX - использовать встроенную оболочку bash printf:

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'

Пример

rename -n 's/HBO_DPM/dpm/' sb_* bash: /usr/bin/rename: Argument list too long

, но

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/' rename(sb_606_HBO_DPM_0089000, sb_606_dpm_0089000) . . . rename(sb_606_HBO_DPM_0163022, sb_606_dpm_0163022)
10
ответ дан 17 July 2018 в 13:56

Поскольку мы предоставляем варианты, вот подход Perl. cd в целевой каталог и запустите:

perl -e 'foreach(glob("sb_*")){rename $_, s/_HBO_DPM_/_dpm_/r}'

Объяснение

perl -e: запустите сценарий, заданный -e. foreach(glob){}: запустите все, что есть в { } по каждому результату glob. glob("sb_*"): вернуть список всех файлов и каталогов в текущем каталоге, имена которых соответствуют оболочке оболочки sb*. rename $_, s/_HBO_DPM_/_dpm_/r: perl магия. $_ - специальная переменная, которая содержит каждый элемент, который мы итерируем (в foreach). Итак, здесь будет найден каждый файл. s/_HBO_DPM_/_dpm_/ заменяет первое вхождение _HBO_DPM_ на _dpm_. Он работает по умолчанию $_, поэтому он будет запускаться для каждого имени файла. [F17] означает «применить эту замену к копии целевой строки (имя файла) и вернуть измененную строку. [F18] делает то, что вы ожидаете: переименовывает файлы, поэтому все это переименует текущий файл имя ($_) к себе с заменой _HBO_DPM_ на _dpm_.

Вы могли бы написать то же самое, что и расширенный (и более читаемый скрипт):

#! /usr/bin/env perl use strict; use warnings; foreach my $fileName (glob("sb_*")){ ## Copy the name to a new variable my $newName = $fileName; ## change the copy. $newName is now the changed version $newName =~ s/_HBO_DPM_/_dpm_/; ## rename rename $fileName, $newName; }
3
ответ дан 17 July 2018 в 13:56

Вы можете сделать это файл по файлу (это может занять некоторое время) с помощью

sudo apt install util-linux # if you don't have it already for i in *; do rename.ul HBO_DPM dpm "$i"; done

Как и Perl rename, используемый в других ответах, rename.ul также имеет опцию -n или --no-act для тестирования.

6
ответ дан 17 July 2018 в 13:56

Я вижу, что никто не пригласил моего лучшего друга sed на вечеринку :). Следующий цикл for выполнит вашу задачу:

for i in sb_606_HBO_DPM*; do mv "$i" "$(echo $i | sed 's/HBO_DPM/dpm/')"; done

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

3
ответ дан 20 July 2018 в 13:59
  • 1
    Конечно, это не очень важно в этом конкретном случае, но это не удастся, если какое-либо из имен файлов содержит символы новой строки. Я упоминаю об этом, так как большинство (все?) Другие ответы являются надежными и могут обрабатывать произвольные имена файлов, или только работают над схемой именования файлов OP. – terdon♦ 22 May 2018 в 13:26
  • 2
    ... новые строки, пробелы, подстановочные знаки ... некоторые из которых можно избежать, указав $i в подстановке команд, но не имея простого способа обработки конечной новой строки в имени файла. – muru 22 May 2018 в 15:27

Вы можете написать небольшой скрипт python, например:

import os for file in os.listdir("."): os.rename(file, file.replace("HBO_DPM", "dpm"))

Сохранить это как текстовый файл как rename.py в папке, в которой находятся файлы, а затем с помощью терминала в этой папке :

python rename.py
6
ответ дан 20 July 2018 в 13:59

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

rename -v 'y/sb_606_HBO_DPM_/sb_606_dpm_/' *
-1
ответ дан 20 July 2018 в 13:59
  • 1
    Это будет запущено в «Список аргументов слишком длинный» & quot; ошибка OP получена. – muru 22 May 2018 в 15:25
  • 2
    Я использовал его в папке со 100 картинками, но я понимаю, что если у вас слишком много файлов, будет сложно выполнить это: / – Florian_PB 23 May 2018 в 16:12

В зависимости от вида переименования, которое вы предполагаете, использование vidir с редактированием нескольких строк может быть удовлетворительным. В вашем конкретном случае вы можете выбрать все строки в текстовом редакторе и удалить часть имен файлов «HBO» в несколько нажатий клавиш.

1
ответ дан 20 July 2018 в 13:59
  • 1
    Да, vi имеет глобальную находку и замену. – Jasen 20 May 2018 в 01:57
  • 2
    Не могли бы вы расширить свой ответ и дать пример того, как достичь цели OP с помощью vidir? – dessert 20 May 2018 в 11:33

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

mmv

Я бы использовал команду mmv из пакета с тем же именем:

mmv '*HBO_DPM*' '#1dpm#2'

Обратите внимание, что аргументы передаются как строки, поэтому расширение glob не происходит в оболочке. Команда получает ровно два аргумента, а затем находит соответствующие файлы внутри, без жестких ограничений на количество файлов. Также обратите внимание, что в приведенной выше команде предполагается, что все файлы, соответствующие первому шару, должны быть переименованы. Конечно, вы можете быть более конкретными:

mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'

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

mmv 'sb_606_HBO_DPM_0089*' 'sb_606_dpm_0089#1' # 0089000-0089999 mmv 'sb_606_HBO_DPM_009*' 'sb_606_dpm_009#1' # 0090000-0099999 mmv 'sb_606_HBO_DPM_01[0-5]*' 'sb_606_dpm_01#1#2' # 0100000-0159999 mmv 'sb_606_HBO_DPM_016[0-2]*' 'sb_606_dpm_016#1#2' # 0160000-0162999 mmv 'sb_606_HBO_DPM_01630[01]?' 'sb_606_dpm_01630#1#2' # 0163000-0163019 mmv 'sb_606_HBO_DPM_016302[0-2]' 'sb_606_dpm_016302#1' # 0163020-0163022

цикл над номерами

Если вы хотите избежать установки чего-либо или вам нужно выбирать по диапазону номеров, избегая соответствует этому диапазону, и вы готовы ждать 74,023 командных вызовов, вы можете использовать простой цикл bash:

for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done

Это работает особенно хорошо, так как в последовательности нет пробелов. В противном случае вам может потребоваться проверить, существует ли исходный файл.

for i in {0089000..0163022}; do test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i done

Обратите внимание, что в отличие от for ((i=89000; i<=163022; ++i)) расширение скобки обрабатывает ведущие нули, поскольку несколько выпусков Bash пару лет назад. На самом деле это изменение, которое я запросил, поэтому я рад видеть его варианты использования.

Дальнейшее чтение: mmv command на информационных страницах Bash, особенно часть {x..y[..incr]} .

loop over files

Другим вариантом будет цикл над подходящим glob, а не просто цикл по целочисленному диапазону, о котором идет речь. Что-то вроде этого:

for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done

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

Дальнейшее чтение: Расширение параметра оболочки на информационных страницах Bash, в том числе документация ${parameter/pattern/string}.

Если вы хотите ограничить диапазон номеров тем, который вы предоставили, вы можете добавить проверьте это:

for i in sb_606_HBO_DPM_+([0-9]); do if [[ "${i##*_*(0)}" -ge 89000 ]] && [[ "${i##*_*(0)}" -le 163022 ]]; then mv "$i" "${i/HBO_DPM/dpm}" fi done

Здесь ${i##pattern} удаляет самый длинный префикс, соответствующий pattern из $i. Этот самый длинный префикс определяется как что-либо, затем подчеркивание, затем нуль или более нулей. Последний записан как *(0), который является расширенным расширением Shell Parameter Expansion , который зависит от установленного пакета с тем же именем . Удаление начальных нулей важно для обработки числа в качестве базы 10, а не базы 8. Параметр +([0-9]) в аргументе цикла представляет собой еще один расширенный глобус, соответствующий одной или нескольким цифрам, на всякий случай, если у вас есть файлы, которые начинаются с того же самого, но не конец в числе.

11
ответ дан 20 July 2018 в 13:59
  • 1
    Спасибо! Это работало как сон: для i в {0089000..0163022}; do mv sb_606_HBO_DPM_ $ i sb_606_dpm_ $ i; done - мне пришлось добавить расширение имени файла, чтобы он работал, но он сделал это именно так, как я хотел, и я даже понимаю синтаксис. Благодарю @MvG – rich 21 May 2018 в 20:21
  • 2
    @rich: Счастлив, что я мог бы помочь - вы и, надеюсь, будущие посетители. Не забудьте принять самый полезный ответ. Вы всегда можете изменить эту галочку в будущем, если произойдет что-то лучше. – MvG 21 May 2018 в 21:25

Один из способов обойти предел ARG_MAX - использовать встроенную оболочку bash printf:

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'

Пример

rename -n 's/HBO_DPM/dpm/' sb_* bash: /usr/bin/rename: Argument list too long

, но

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/' rename(sb_606_HBO_DPM_0089000, sb_606_dpm_0089000) . . . rename(sb_606_HBO_DPM_0163022, sb_606_dpm_0163022)
10
ответ дан 20 July 2018 в 13:59

Поскольку мы предоставляем варианты, вот подход Perl. cd в целевой каталог и запустите:

perl -e 'foreach(glob("sb_*")){rename $_, s/_HBO_DPM_/_dpm_/r}'

Объяснение

perl -e: запустите сценарий, заданный -e. foreach(glob){}: запустите все, что есть в { } по каждому результату glob. glob("sb_*"): вернуть список всех файлов и каталогов в текущем каталоге, имена которых соответствуют оболочке оболочки sb*. rename $_, s/_HBO_DPM_/_dpm_/r: perl магия. $_ - специальная переменная, которая содержит каждый элемент, который мы итерируем (в foreach). Итак, здесь будет найден каждый файл. s/_HBO_DPM_/_dpm_/ заменяет первое вхождение _HBO_DPM_ на _dpm_. Он работает по умолчанию $_, поэтому он будет запускаться для каждого имени файла. [F17] означает «применить эту замену к копии целевой строки (имя файла) и вернуть измененную строку. [F18] делает то, что вы ожидаете: переименовывает файлы, поэтому все это переименует текущий файл имя [$_) к себе с заменой _HBO_DPM_ на _dpm_.

Вы можете написать то же самое, что и расширенный (и более читаемый скрипт):

#! /usr/bin/env perl use strict; use warnings; foreach my $fileName (glob("sb_*")){ ## Copy the name to a new variable my $newName = $fileName; ## change the copy. $newName is now the changed version $newName =~ s/_HBO_DPM_/_dpm_/; ## rename rename $fileName, $newName; }
3
ответ дан 20 July 2018 в 13:59

Вы можете сделать это файл по файлу (это может занять некоторое время) с помощью

sudo apt install util-linux # if you don't have it already for i in *; do rename.ul HBO_DPM dpm "$i"; done

Как и Perl rename, используемый в других ответах, rename.ul также имеет опцию -n или --no-act для тестирования.

6
ответ дан 20 July 2018 в 13:59
  • 1
    Я отредактировал Ваш комментарий о ответ Занна, пожалуйста, отредактируйте Занна ответ или оставить комментарий. – ubashu 25 May 2018 в 01:30
  • 2
    @ubashu, который не был комментарием к моему ответу - это имел в виду флаг -n, который я использовал для тестирования, и предлагаю его использовать в rename.ul тоже. – Zanna 3 June 2018 в 15:28

Другие вопросы по тегам:

Похожие вопросы: