尝试使用 find 的包装器但遇到以下问题。例如,我希望提供一些目录作为参数,但最后一个参数始终是一个数字,指示应删除多旧的数据。例如:
rmoldfiles dir1 dir2 dir3 20
这应该会删除超过 30 天的旧文件looking at mtime of course
这是脚本:
#!/bin/bash
die()
{
echo >&2 "$@"
exit 1
}
usage()
{
echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
die
}
if [[ (($# < 1)) || -f "$1" ]]; then
if [[ -f "$1" ]]; then
printf '%s\n' "Please provide a directory"
fi
usage
fi
while (( $# )); do
while IFS= read -r -d $'\0' file; do
printf 'rm %s\n' "$file"
sleep 1
done < <(find "$1" -type f -mtime +$2 -print0)
shift
done
echo "Done deleting"
问题
如何shift
目录但不是最后一个参数。
答案1
几个解决方案。
选出最后一个命令行参数。
args=( "$@" ) num=${args[-1]} args=( "${args[@]:0:${#args[@]} - 1}" )
(然后用于
find "${args[@]}" -type f -mtime "+$num" -print -delete
删除这些文件)。先把号码放上去。
num=$1; shift
(然后用于
find "$@" -type f -mtime "+$num" -print -delete
删除文件)。
仅当您有数百或数千个目录需要处理时才需要循环,在这种情况下,find
单次调用命令会太长。否则,不要循环。find
可以采用多个搜索路径。
如果您想插入延迟并rm
显式使用,并且为每个文件提供一些格式化输出:
find "$@" -type f -mtime "+$num" -exec sh -c '
for pathname do
printf "Removing %s\n" "$pathname"
rm -- "$pathname"
sleep 1
done' sh {} +
如果你发现你做需要循环遍历目录(或者如果这样感觉更好):
# Assumes that the arguments are in the order
# num dir1 dir2 dir3 ...
num=$1
shift
for dir do
printf 'Processing %s...\n' "$dir"
find "$dir" -type f -mtime "+$num" -exec sh -c '
for pathname do
printf "Removing %s\n" "$pathname"
rm -- "$pathname"
sleep 1
done' sh {} +
done
或者,
# Assumes that the arguments are in the order
# dir1 dir2 dir3 ... num
args=( "$@" )
num=${args[-1]}
args=( "${args[@]:0:${#args[@]} - 1}" )
for dir in "${args[@]}"; do
# as above
done
答案2
由于您只期望(并提供)年龄参数之前的三个目录,因此不要不加区别地循环;相反,显式循环:
for dir in 1 2 3; do
# work with "$1"
shift
done
或者当剩下一个参数时停止循环:
while [ "$#" -gt 1 ]; do
echo "Work with $1"
shift;
done
由于“days”参数在每个班次期间都会移动,因此您需要首先将其保存:
days=$4
...在调用循环之前。
...如果您允许传递任意数量的目录:
[ "$#" -gt 1 ] || exit 1
days=${@: -1}
while [ "$#" -gt 1 ]; do
echo work with "$1" and "$days"
shift
done
这使用 bash 数组$@
并要求它的最后一个元素(由 表示-1
,用空格分隔以防止它被解释为 的修饰符:
);然后它逐个循环参数,直到剩下一个(最后的初始“day”参数)。
答案3
只需更改(( $# ))
为(( $# > 1))
:
while (( $# > 1 )); do
echo "file is: $1"
done
echo "days are: $1"