Допустим, у меня есть каталог source/
, в котором много подкаталогов. Некоторые из этих подкаталогов имеют под-подкаталоги, а некоторые из этих подкаталогов имеют под-подкаталоги и т. Д.
Что я хочу сделать, так это рекурсивно найти все подкаталоги самого низкого уровня (подкаталоги, которые не имеют каких-либо дополнительных подкаталогов) из source/
и переместить их в новый целевой каталог.
Например, предположим, что оригинал source/
выглядит следующим образом:
/source/dir1 --Subdirectory without sub-subdirectory
/source/dir2 --Subdirectory with sub-subdirectory
/source/dir2/dir2.a --Sub-subdirectory without sub-sub-subdirectory
/source/dir2/dir2.b --Sub-subdirectory without sub-sub-subdirectory
Тогда после операции каталог target
должен выглядеть следующим образом:
/target/dir1
/target/dir2.a
/target/dir2.b
Есть ли способ сделать это с помощью команды терминала?
Принятие Вас находится в файловой системе, где листовые каталоги имеют точно 2 жестких ссылки, можно использовать комбинацию находки, xargs и mv как так:
$ find . -type d -printf "%n %p\n" \
| grep '^2 ' \
| perl -ne 'chomp; s/[0-9]+\s+//; print "$_\0";' \
| xargs -0 -I'{}' mv -v '{}' /target/
Это использует, находят, чтобы найти только каталоги и распечатать количество жестких ссылок, которые имеют те каталоги.
Затем мы используем grep для удаления любого, которые не являются "листами".
Затем мы используем Perl, чтобы обрубить количество жесткой ссылки и распечатать файлы, разделенные \0
.
Наконец это позволяет нам использовать xargs с -0
отметьте для перемещения найденных каталогов в целевой каталог.
Используя пустые указатели (\0
) вместо новых строк или пробелов важно для файлов с пробелами в них. Если Ваши имена каталогов, как гарантируют, не будут иметь пробелы в них, Вы смогли упрощать немного.
$ find . -type d -printf "%n %p\n" | grep '2 ' | cut -d " " -f 2 | xargs -I'{}' mv -v '{}' /target/
Но, вероятно, лучше быть безопасным, чем извините.
Один подход мог бы быть должен использовать find
получить каждый каталог и передать результаты секунде find
, и выполните перемещение только если второе find
делает для возврата любых каталогов ниже, учитывая один, например.
while read -rd $'\0' dir; do
[[ -z $(find "$dir" -mindepth 1 -type d) ]] && mv -t path/to/target "$dir"
done < <(find -depth -type d -print0)
или
find -depth -type d -execdir \
bash -c '[[ -z $(find "$0" -mindepth 1 -type d) ]] && mv -t path/to/target "$0"' {} +
например, данный
$ tree .
.
├── dir1
└── dir2
├── dir2.a
└── dir2.b
затем
$ while read -rd $'\0' dir; do [[ -z $(find "$dir" -mindepth 1 -type d) ]] && echo mv -t path/to/target "$dir"; done < <(find -depth -type d -print0)
mv -t path/to/target ./dir1
mv -t path/to/target ./dir2/dir2.b
mv -t path/to/target ./dir2/dir2.a