Может быть скрипт типа:
#! /bin/sh -
dir=${1?Please specify the directory to sort}
cutoff=${2:-1048576} # bytes
cd -P -- "$dir" || exit
mkdir -p -- small_files large_files || exit
find. ! -name. -prune -type f '(' \
-size "+${cutoff}c" -exec sh -c 'exec mv -- "$@" large_files' sh {} + -o \
-exec sh -c 'exec mv -- "$@" small_files' sh {} + ')'
В системе GNU вы можете передать параметр -v
в mv
и mkdir
, чтобы сделать его более подробным. С помощью инструментов GNU это можно упростить до:
#! /bin/sh -
dir=${1?Please specify the directory to sort}
cutoff=${2:-1M}
cd -P -- "$dir" || exit
mkdir -p -- small_files large_files || exit
find. -maxdepth 1 -type f '(' \
-size "+$cutoff" -exec mv -t large_files {} + -o \
-exec mv -t small_files {} + ')'
С этой опцией -t
для указания целевого каталога нам больше не нужно вызывать sh
для вставки списка имен файлов в середину аргументов mv
.
Вы можете добавить дополнительные категории, например:
find. -maxdepth 1 -type f '(' \
-size +1M -exec mv -t large_files {} + -o \
-size +100k -exec mv -t medium_files {} + -o \
-exec mv -t small_files {} + ')'
С помощью zsh
вы также можете сделать это как:
#! /bin/zsh -
dir=${1?Please specify the directory to sort}
cd -P -- "$dir" || exit
for size target (
LG+1 huge_files
LM+100 very_large_files
LM+1 large_files
LK+100 medium_sized_files
L+100 small_files
'' tiny_files
) {
mkdir -p $target || exit
files=(*(NDoN.$size))
(($#files == 0)) || mv -- $files $target || exit
}
Один из способов может быть с find/grep/sed
, как показано:
find. -maxdepth 1 -type f -name '*.txt' \
-exec grep -q '[[:blank:]]$' {} \; \
-exec sed -Ei -e 's/[[:blank:]]+$//' {} +
{} \;
относится к имени файла, передаваемого в grep
, а \;
экранирует точку с запятой метасимвола оболочки, которая является индикатором конца команды. Мы выходим из него так, чтобы он достиг -exec
. В качестве альтернативы вы могли бы написать это как';'
{} +
вы уже знаете {}
сейчас, и что +
означает, что вы передаете как можно больше имен файлов вsed
(в основном,вместо передачи единственного {}
текущего результата find
, накопите список {}
для использования в качестве аргумента перед вызовомsed
). Это позволяет минимизировать количество sed
вызовов. Следующее строится на идее roaima запускать выражение sed
во всех файлах, но затем сохранять только те файлы, которые были фактически изменены.
Он изменяет это, делая меньше sed
вызовов:
printf '%s\0'./*.txt |
xargs -0 sed -i.bak 's/[[:blank:]]$//
Затем вы можете просмотреть файлы *.txt
, сравнив их с оригиналами и выбрав тот, который хотите сохранить.:
for name in./*.txt; do
if cmp -s "$name" "$name.bak"; then
# keep original
mv "$name.bak" "$name"
else
# keep modified
rm "$name.bak"
fi
done
Или сделать и то, и другое за один раз:
printf '%s\0'./*.txt |
xargs -0 sh -c '
sed -i.bak "s/[[:blank:]]$//" "$@"
for name do
if cmp -s "$name" "$name.bak"; then
mv "$name.bak" "$name"
else
rm "$name.bak"
fi
done' sh