如何获取此“for”循环所需的输入?

如何获取此“for”循环所需的输入?

我编写了一个小脚本来备份从 TOR 下载的内容,因为有时 TOR 会尝试提前合并其占位符文件(具有原始文件名的零字节文件)和其实际下载文件(原始文件加扩展名.part),这将导致丢失所有数据。

作为此脚本的补充,我想让脚本.part在下载完成后删除备份文件。问题是,下载的文件名经常包含空格或特殊字符,迫使我使用双引号,这种方法非常有效,直到我下载了多个文件,此时将find所有文件展开在一行上,并且我的文件中没有匹配项测试声明。

也许我的方法都是错误的,但如果不是,我怎样才能获得命令的单独文件名rm

#!/system/bin/sh
if [ ! -d /sdcard/Download/tordownloadbackup ]; then
mkdir /sdcard/Download/tordownloadbackup
fi
echo 'backing-up'
find /sdcard/Download/ -maxdepth 1 -name '*.part' -print -exec cp {} /sdcard/Download/tordownloadbackup/ \;

for f in "`find /sdcard/Download/tordownloadbackup/ -type f |rev |cut -c 6-100| cut -d / -f 1 |rev`"; do

if [ -s /sdcard/Download/"$f" ]; then
    if [ -f /sdcard/Download/tordownloadbackup/"$f".part ]; then
    rm /sdcard/Download/tordownloadbackup/"$f".part
    d="$f".part
    echo "deleting $d"
    fi
fi
done
sleep 300
~/run.sh

答案1

如果您确定文件名中没有换行符,那么您可以这样做:

find /sdcard/Download/tordownloadbackup/ -type f -printf '%f\n' |
    awk '{ print substr($0,1,length($0)-5); }' |
    while IFS= read -r filename; do
        : ...
    done

路径中任何字符的一般方法是:

find . -exec bash -c 'ls -l "$@"' bash {} +

答案2

这个命令:

for f in "`find /sdcard/Download/tordownloadbackup/ -type f | ...

看起来很尴尬并且容易出错。确实不鼓励使用 来迭代打印的文件列表for

迭代findbash 中找到的文件的最可靠方法是使用 aread和 null 终止的字符串。在将命令的输出通过管道传输到< <(command)后使用,这称为whileread流程替代

while IFS= read -r -d $'\0' file; do
    # Arbitrary operations on "$file" here
done < <(find /some/path -type f -print0)

感谢@SiegeX 的旧回答:https://stackoverflow.com/questions/8677546/reading-null-delimited-strings-through-a-bash-loop

而且,rev |cut -c 6-100| cut -d / -f 1 |rev看上去也很奇怪。我认为这应该打印目录基本名称。为此,请使用 bash 内置字符串操作 或dirnameand 。basename

因此,您最终可能会将此循环重写为(使用字符串操作,因为内置,所以速度更快):

while IFS= read -r -d $'\0' file; do
  Filebasename="${file##*/}"
  Dirname="${file%/*}"
  Dirbasename="${Dirname##*/}"
  # other stuff here
done < <(find /sdcard/Download/tordownloadbackup/ -type f -print0)

有关子字符串删除的更多信息,请参阅Linux 文档项目

或者使用basenameand dirname(由于外部程序而较慢):

while IFS= read -r -d $'\0' file; do
  Dirbasename="$(basename -- "$(dirname -- "$file")")"
  # other stuff here
done < <(find /sdcard/Download/tordownloadbackup/ -type f -print0)

相关内容