У меня следующая проблема. У меня есть папка, в этой папке около 100 разных папок, в каждой из этих папок около 500 файлов. Я хочу сохранить только первые 100 файлов из каждой папки.
Я смотрю на while / loops, но не могу понять это. (У меня вообще нет навыков написания сценариев) Я видел и играл с некоторыми сценариями, но не могу заставить его собрать первые 100 файлов из каждой папки.
Может быть, есть более простой способ сделать это?
Заранее спасибо!
Принятие Ваших имен файлов не содержит пробелы или другие странные символы,
Можно получить в алфавитном порядке первые 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
Если Вы имеете 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 (.)
простой спецификатор файла здесь - это будет соответствовать и пытаться удалить каталоги также, если будет кто-либо.