Я провел почти полтора дня, ища это, но не мог найти ответ.
Я надеюсь добавлять имя папки как префикс во все файлы, заканчивающиеся .bin
в той папке.
Так, если имя папки ABC
и это содержит файлы aa.bin
, bb.bin
, cc.bin
, и т.д. затем мне нужны они, чтобы быть переименованным как ABC-aa.bin
, ABC-bb.bin
, ABC-cc.bin
, и т.д.
Кроме того, эта папка ABC
имеет подпапки, давайте назовем их: ABC1
, ABC2
, ABC3
, и т.д., которые также имеют .bin
файлы. Например, ABC1
имеет aa1.bin
, bb1.bin
, cc1.bin
, и т.д.
Мне нужна та команда, чтобы пройти все папки и добавить имя той подпапки к файлам в нем также. Так, aa1.bin
будет ABC1-aa1.bin
, и так далее.
Структура каталогов:
.
└── ABC
├── aa.bin
├── ABC1
│ ├── aa1.bin
│ └── bb1.bin
├── ABC2
│ ├── aa2.bin
│ └── bb2.bin
├── bb.bin
└── cc.bin
Вот "острота", чтобы сделать, с помощью оболочки, созданной-ins для управления именами файлов:
find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "$1" "$p/${p##*/}-$f"' sh {} \;
Тест это в целевом каталоге и удаляет echo
, если результаты выглядят корректными
, например, учитывая
$ tree .
.
└── ABC
├── aa.bin
├── ABC1
│ ├── aa1.bin
│ └── bb1.bin
├── ABC2
│ ├── aa2.bin
│ └── bb2.bin
├── bb.bin
└── cc.bin
3 directories, 7 files
затем
$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "$1" "$p/${p##*/}-$f"' sh {} \;
mv -- ./ABC/ABC2/bb2.bin ./ABC/ABC2/ABC2-bb2.bin
mv -- ./ABC/ABC2/aa2.bin ./ABC/ABC2/ABC2-aa2.bin
mv -- ./ABC/aa.bin ./ABC/ABC-aa.bin
mv -- ./ABC/bb.bin ./ABC/ABC-bb.bin
mv -- ./ABC/ABC1/bb1.bin ./ABC/ABC1/ABC1-bb1.bin
mv -- ./ABC/ABC1/aa1.bin ./ABC/ABC1/ABC1-aa1.bin
mv -- ./ABC/cc.bin ./ABC/ABC-cc.bin
хорошие взгляды, поэтому удалите echo
и выполните его снова
$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; mv -- "$1" "$p/${p##*/}-$f"' sh {} \;
предоставление
$ tree .
.
└── ABC
├── ABC1
│ ├── ABC1-aa1.bin
│ └── ABC1-bb1.bin
├── ABC2
│ ├── ABC2-aa2.bin
│ └── ABC2-bb2.bin
├── ABC-aa.bin
├── ABC-bb.bin
└── ABC-cc.bin
3 directories, 7 files
Можно сделать это при помощи find
, basename
, dirname
и mv
команды. Например, как в этом простом сценарии:
#!/bin/bash
for f in $(find ABC -name '*.bin');
do
filename="$(basename $f)"
dir="$(dirname $f)"
lastdir="$(basename $dir)"
newname="$lastdir-$filename"
newpath="$dir/$newname"
mv $f $newpath
done
Здесь я использую, находят, чтобы рекурсивно найти весь .bin
файлы в ABC, затем выполнить итерации по ним и извлечению последнего имени папки. Затем новый путь создается, и файл перемещен в тот же каталог, но с новым именем.
Редактирование :
для выполнения этого сценария, копируют его содержание в некоторый файл. Скажем, имя файла renameFiles.sh
. Затем сделайте это исполняемым файлом:
chmod +x renameFiles.sh
После этого можно выполнить его с ./renameFiles.sh
. Заметьте, что папка, куда Вы помещаете этот файл, должна быть тем же, где Ваша папка ABC расположена.
renameFiles.sh
ABC
aa.bin
bb.bin
ABC1
aa1.bin
etc.
Используя rename
:
shopt -s globstar
rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
shopt -s globstar
: Если установлено, шаблон '**' используемый в контексте расширения имени файла будет соответствовать всем файлам и нулю или большему количеству каталогов и подкаталогов. Если шаблон сопровождается '/', только соответствие подкаталогов и каталоги.rename -n '! -f $_ && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
: выполняет пробный прогон следующего. Для каждого имени файла, следующего **
globbing: если файл не является регулярным файлом, или имя файла не заканчивается .bin
, пропуски к следующему имени файла; устанавливает выходного разделителя полей на /
; разделяет имя файла на /
; предварительно ожидает предпоследнее поле, сопровождаемое -
к последнему полю; присваивает новое имя файла переменной по умолчанию ($_
).Если результатом является ожидаемый, удалите -n
опция от rename
команда.
$ tree
.
└── ABC
├── aa.bin
├── ABC1
│ ├── aa1.bin
│ └── bb1.bin
├── ABC2
│ ├── aa2.bin
│ └── bb2.bin
├── bb.bin
└── cc.bin
3 directories, 7 files
$ rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/aa.bin, ABC/ABC-aa.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC1/aa1.bin, ABC/ABC1/ABC1-aa1.bin)
rename(ABC/ABC1/bb1.bin, ABC/ABC1/ABC1-bb1.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC2/aa2.bin, ABC/ABC2/ABC2-aa2.bin)
rename(ABC/ABC2/bb2.bin, ABC/ABC2/ABC2-bb2.bin)
rename(ABC/bb.bin, ABC/ABC-bb.bin)
rename(ABC/cc.bin, ABC/ABC-cc.bin)