朋友们,
我有一个小型的基本 shell 脚本,用于压缩目录和子目录中的文件。但是,我需要添加一个计数器,以便只压缩一定数量的文件(例如 50 个文件)。我无法完成,请提供建议。请在下面找到我的脚本。
#!/bin/bash
BASEDIR=/home/tmp
cd "${BASEDIR}"
pwd
for i in `find . -name *.jpg -type f -print -mtime +30`
do
zip ${i%.*} $i
echo "Process Completed"
done
请指教?非常感谢您的帮助。
答案1
有几件事需要解决:
- 不要使用反引号;
$(...)
现在通常更倾向于使用反引号,特别是因为它们可以处理嵌套引用。这里没有问题,但要注意这一点 find
应与循环一起使用,while
以对文件名进行复杂的处理。While 循环也有助于模仿 C 风格的 for 循环,事实上,在编程中,您可以在任一循环中实现相同的行为,这是一个常见的概念。- 如果要添加到现有 zip 文件,请使用
-u
标志进行更新,如“$current_file”zip -u zipfile.zip
因此,你的脚本最好写成
#!/bin/bash
# using capitals for variable names
# can be confusing and interfere with env
# or shell variables
basedir=/home/tmp
cd "${basedir}"
# You can use variable instead of pwd command
printf "Current working directory:%s\n" "$PWD"
counter=0
# pipelines can be broken to multiple lines
find . -name '*.jpg' -type f -print0 -mtime +30 |
while IFS= read -r f_name; do
counter=$((counter+1))
zip u ${i%.*} "$f_name"
# This is where you check for number of files processed
if [ "$counter" -eq 50 ]; then
break
fi
done
如果这太冗长和冗长,我们可以用标志来玩一点find
,-exec
但问题是我们不能在-exec
调用之间共享变量。因此我们可以使用临时文件。我们还需要以某种方式停止在所有大于限制的文件上find
调用我们的-exec
进程,这样我们就可以杀死变量指定的 shell 的父进程$PPID
。
cd "$basedir"
find -type f -name '*.jpg' -mtime +30 -exec bash -c '
f=/tmp/zip.counter;
[ -e "$f" ] && c=$(cat /tmp/zip.counter);
c=$((c+1));
[ "$c" -ge 50 ] && kill $(awk "/^Pid:/ {print $2}");
zip u ${i%.*} "$1";
echo "$c" > "$f"' sh {} \; && rm /tmp/zip.counter
当然,这个解决方案不太实用,而且可以说比while
循环的可读性更低。这只是为了好玩。