Копирование первых 100 файлов из нескольких папок в одну папку (или удаление остальных)

У меня следующая проблема. У меня есть папка, в этой папке около 100 разных папок, в каждой из этих папок около 500 файлов. Я хочу сохранить только первые 100 файлов из каждой папки.

Я смотрю на while / loops, но не могу понять это. (У меня вообще нет навыков написания сценариев) Я видел и играл с некоторыми сценариями, но не могу заставить его собрать первые 100 файлов из каждой папки.

Может быть, есть более простой способ сделать это?

Заранее спасибо!

-1
задан 10 July 2019 в 17:41

2 ответа

Принятие Ваших имен файлов не содержит пробелы или другие странные символы,

Можно получить в алфавитном порядке первые 100 файлов в каталоге с:

find . -maxdepth 1 -type f -print | sort |head -n 100

но, для получения всех других файлов (те Вы хотите к "не, сохраняют":

find . -maxdepth 1 -type f -print | sort |tail  -n +101

Затем замена * со списком папок сделайте:

for f in * ; do
    cd $f
    # to delete all but the first 100
    find . -maxdepth 1 -type f -print | sort |tail  -n +101 | xargs rm
    # or, to copy them elsewhere
    mkdir ../new_$f
    find . -maxdepth 1 -type f -print | sort |head -n 100 | \
        xargs cp --target-directory=../new_$f

    # remember to undo initial cd $f
    cd ..
done
0
ответ дан 24 October 2019 в 00:17

Если Вы имеете zsh, такого рода вещь является легким использованием ее спецификаторов шарика. Принимая во внимание, что * соответствиями по умолчанию все нескрытые файлы (включая каталоги), zsh позволяет Вам использовать шарики как *(.[1,100]) относиться к первым 100 простым файлам (заказанный лексически по имени) или *(.[101,-1]) соответствовать всем простым файлам после 100-го. Так, например, Вы могли сделать

for d in *(/); do echo rm -- "$d"/*(.[101,-1]); done

для (отзываний эхом) удаляют все кроме (лексически) первых 100 файлов от каждого подкаталога текущего каталога.

Если получающийся список аргументов является слишком длинным, Вы могли бы изменить вышеупомянутое к

for d in *(/); do print -rN -- "$d"/*(.[101,-1]) | xargs -r0 echo rm -- ; done

Удалите echo только, после того как Вы абсолютно уверены, что это соответствует намеченным файлам.

Скопировать первые 100 файлов вместо того, чтобы удалить все остальные, также

for d in *(/); do echo cp -t path/to/dest -- "$d"/*(.[1,100]); done

или если список аргументов является слишком длинным

for d in *(/); do 
  print -rN -- "$d"/*(.[1,101]) | xargs -r0 echo cp -t path/to/dest/ --
done

Для достижения почти того же в ударе способом, это безопасно для любого легального имени файла, которое Вы могли использовать set и shift builtins:

for d in */; do set -- "$d"*; shift 100; echo rm -- "$@"; done

или если список аргументов является слишком длинным

for d in */; do 
  set -- "$d"*; shift 100; printf -- '%s\0' "$@" | xargs -r0 echo rm --
done

Обратите внимание, что нет никакого эквивалента zsh (.) простой спецификатор файла здесь - это будет соответствовать и пытаться удалить каталоги также, если будет кто-либо.

0
ответ дан 24 October 2019 в 00:17

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

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