Переместить все подкаталоги самого низкого уровня (но НЕ каталоги или файлы среднего уровня) в целевой каталог

Допустим, у меня есть каталог 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

Есть ли способ сделать это с помощью команды терминала?

0
задан 1 June 2014 в 18:46

2 ответа

Принятие Вас находится в файловой системе, где листовые каталоги имеют точно 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/

Но, вероятно, лучше быть безопасным, чем извините.

1
ответ дан 1 June 2014 в 18:46

Один подход мог бы быть должен использовать 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
0
ответ дан 1 June 2014 в 18:46

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

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