perl -l -0777ne 'print for /(?:^|\n)\n\K.+(?=\n\n)/g' yourfile
Объяснение:
Мы сжимаем файл, и весь файл представляет собой одну запись. В этой единственной записи мы увеличиваем
острова
, которым предшествуют 2 последовательных начала строки и за которыми следуют 2 новые строки. Все такиеострова
печатаются цикломfor
.
sed -e '
/./d # skip a nonempty line
$!N # grab the line following an empty line
/^\n$/D # if we have 2 consecutive empties, clip the former, n branch to top
$!N # we now have ^\nLine\n...
/\n$/!D # clip if the seq ^\nLine\n$ not found
s/.// # found it! ^\nLine\n$
P;D #
' yourfile
Прежде всего,
я не могу воспроизвести результаты, которые вы заявляете для команды, которую вы показали.
Я получил файлы, которые переименовываются в другой файл_каталога1.jpg
,
другой файл_каталога2.jpg
и т. Д.,
но все же в некоторых каталогах
каталогах.
Во-вторых, из-за глубины структуры каталогов
вам следует использовать -mindepth 4
вместо 2
.
В-третьих, я настоятельно рекомендую вам использовать -тип f
.
Пока вы используете -name '* .jpg'
,
вы, вероятно, не найдете никаких каталогов.
Но через шесть-восемь недель
вы посмотрите на это и подумаете: «Я хочу, чтобы это применимо ко всем моим файлам
- мне не нужно говорить -name '*.jpg '
», и выньте его.
А затем, если у вас нет -типа f
,
команда find
может начать поиск каталогов и их переименование.
А изменение дерева каталогов во время его сканирования
- это верный путь к катастрофе
(например, пословица «летать на самолете, пока мы его строим»).
В-четвертых, команда rename для перемещения файла на три уровня вверх
и префикса его имени с помощью Directory
rename -n 's!/[^/]+/[^/]+/([^/]+)$!_$1!' (optionally)
, потому что / [^ /] +
представляет уровень каталога,
поэтому я просто добавил еще две его копии.
Предупреждение: это, как я уже сказал, переместит файл на три уровня вверх.
Если у вас есть файлы, расположенные глубже в дереве каталогов,
они не будут переименованы в верхний уровень;
они могут быть переименованы во что-то вроде Directory 3 / некоторый файл_каталога3.jpg
.
Но оказывается, это легко исправить.
Чтобы переместить файл на верхний уровень с любой глубины, на которой он находится на ,
и добавьте к его имени префикс Directory
,
просто используйте
s!(\./[^/]+)/.*/([^/]+)$/$1_$2/!
Последняя команда -
find . -mindepth 4 -type f -exec rename -n 's!/[^/]+/[^/]+/([^/]+)$!_$1!' {} +
Добавить -name '* .jpg'
, если хотите.
Удалите -n
, когда выходные данные трассировки показывают, что все работает правильно.
Помните, что это может привести к конфликту файлов. Если у вас есть файлы
Directory 1/some directory/another directory/sunrise.jpg
и
Directory 1/some directory/another directory/mountains/sunrise.jpg
, эта команда попытается переименовать их оба в Directory 1_sunrise.jpg
.
К счастью, программа переименовать
кажется достаточно умной и дружелюбной
, чтобы не причинить вреда в этом случае.
Первый такой файл, который он увидит, (вероятно) будет переименован;
остальные останутся на месте (и вы получите уведомление).
(Вы можете использовать -f
или - force
, чтобы принудительно перезаписать существующие файлы.)
Но помните, что некоторые другие программы (например,, mv
)
имеют менее дружественные действия по умолчанию.
Относительно обновленного вопроса
(«Как я могу включить все имена каталогов в имена файлов?»):
это немного сложнее.
Я предполагаю, что мы ищем .
,
, поэтому все пути будут начинаться с ./
.
И я обнаружил, что аргумент perlexpr для переименовать
на самом деле может содержать несколько команд изменения строки.
Таким образом, мы можем переместить все файлы на верхний уровень
и добавить к их именам все имена каталогов в пути с помощью
s!^\./!!;s!/!_!g
. Это также может привести к конфликту файлов.
Directory 1/abc/def_ghi/sunrise.jpg
и
Directory 1/abc_def/ghi/sunrise.jpg
(потенциально) будут переименованы в Directory 1_abc_def_ghi_sunrise.jpg
.
Заявление об ограничении ответственности: Я тестировал это, но не совсем тщательно. Я не гарантирую, что это будет работать идеально. Перед выполнением вышеуказанных команд необходимо сделать полную резервную копию.