赞
踩
我脚本中执行find "$directory" -type f -name "*.jpg" -printf "%T@ %p\n" | sort -n | head -n $num_to_delete | awk '{print $2}' | xargs rm
提示:
sort: write failed: 'standard output': Broken pipe
sort: write error
find "$directory" -type f -name "*.jpg" -printf "%T@ %p\n" | sort -n | head -n $num_to_delete | awk '{print $2}' | xargs rm
命令这段代码是一个shell命令,用于删除指定目录下最旧的若干个jpg文件。
解释各部分的含义如下:
find "$directory" -type f -name "*.jpg"
:使用find
命令在指定目录下查找所有的jpg文件。"$directory"
是要查找的目录路径,-type f
表示只查找文件,-name "*.jpg"
表示只查找文件名以.jpg结尾的文件。
-printf "%T@ %p\n"
:-printf
选项用于指定输出格式。%T@
表示输出文件的最后修改时间(以秒为单位),%p
表示输出文件的路径。\n
表示输出换行。
| sort -n
:使用sort
命令对前一步输出的结果进行排序。-n
表示按照数值大小进行排序。
| head -n $num_to_delete
:使用head
命令取前面排序结果中的前$num_to_delete
行。$num_to_delete
是一个变量,表示要删除的文件数量。
| awk '{print $2}'
:使用awk
命令提取前一步输出结果中的第二列(即文件路径)。{print $2}
表示打印第二列。
| xargs rm
:使用xargs
命令将前一步输出的文件路径作为参数传递给rm
命令,从而删除这些文件。
这个错误通常是由于管道中的某个命令提前退出导致的。在命令中,sort
命令的输出被传递给head
命令,然后再传递给awk
命令,最后传递给xargs
命令。当head
命令读取到指定的行数后,它会提前退出,这可能导致sort
命令无法将所有数据写入管道,从而引发"Broken pipe"错误。
head
命令是用来显示文件的开头几行,默认情况下显示前10行。当指定了-n
参数后,head
命令会显示指定行数的内容,并在显示完指定行数后退出。
在上述命令中,head -n $num_to_delete
的作用是显示sort
命令输出的前$num_to_delete
行。一旦head
命令显示完指定行数的内容,它就会提前退出,不再等待后续的输入。
由于sort
命令的输出是通过管道传递给head
命令的,当head
命令提前退出时,管道中的写入端会被关闭,而sort
命令可能还在尝试写入数据,这就导致了"Broken pipe"错误。
awk
命令的NR
功能替换head -n
,换成find "$directory" -type f -name "*.jpg" -printf "%T@ %p\n" | sort -n | awk -v num=$num_to_delete 'NR <= num {print $2}' | xargs rm
可以使用awk
命令来实现head
命令的功能,awk -v num=$num_to_delete 'NR <= num {print $2}'
不会像head -n
命令那样提前关闭管道输出。
修改后的命令如下:
find "$directory" -type f -name "*.jpg" -printf "%T@ %p\n" | sort -n | awk -v num=$num_to_delete 'NR <= num {print $2}' | xargs rm
解释:
当使用awk
命令时,可以使用-v
选项来定义一个变量。在这个命令中,我们使用-v num=$num_to_delete
将Shell变量$num_to_delete
传递给awk
命令,并将其赋值给awk
的变量num
。
awk
命令中的NR
表示当前处理的行号,$2
表示当前行的第二个字段。通过NR <= num
,我们限制了只处理行号小于等于num
的行。然后,对于满足条件的行,我们使用{print $2}
来打印第二个字段。
换句话说,这个awk
命令的作用是只打印前num_to_delete
行的第二个字段。在命令中,这个awk
命令的输出将作为xargs
命令的输入,用于删除相应的文件。
替换了后,现在没再报错了:
另一个避免管道错误的方法是使用临时文件而不是管道:
tmpfile=$(mktemp)
find "$DIRECTORY" -type f -printf '%T@ %p\n' | sort -n > "$tmpfile"
head -n "$num_files_to_delete" "$tmpfile" | cut -d' ' -f2- | xargs -d '\n' -r rm
rm "$tmpfile"
这种方法通过避免直接的管道通信来规避“Broken pipe”错误,因为数据首先被写入临时文件,然后再从文件中读取需要的部分数据。
这个脚本的每一部分都是为了安全有效地删除目录中最旧的一定数量的文件而设计的。下面是每一部分的详细解释:
创建临时文件:
tmpfile=$(mktemp)
这行代码使用 mktemp
命令创建一个临时文件,并将其路径存储在变量 tmpfile
中。mktemp
自动生成一个唯一的文件名,通常位于系统的临时文件夹下(如 /tmp
),这保证了文件名的唯一性,避免了文件名冲突。
查找和排序文件:
find "$DIRECTORY" -type f -printf '%T@ %p\n' | sort -n > "$tmpfile"
find "$DIRECTORY" -type f -printf '%T@ %p\n'
:这个 find
命令搜索指定目录($DIRECTORY
)下的所有文件(不包括目录),并对每个文件输出其最后修改时间(以 Unix 时间戳格式)和路径。输出格式为时间戳和路径之间有一个空格分隔。sort -n
:这个 sort
命令按数字顺序(-n
)对输入进行排序,因为时间戳是数字,所以这会按照文件的修改时间从旧到新排序。> "$tmpfile"
:将 sort
命令的输出重定向到临时文件中。这样做可以避免在管道中处理大量数据时可能出现的问题。提取并删除文件:
head -n "$num_files_to_delete" "$tmpfile" | cut -d' ' -f2- | xargs -d '\n' -r rm
head -n "$num_files_to_delete" "$tmpfile"
:这个 head
命令从临时文件中读取前 $num_files_to_delete
行,即最旧的那些文件的路径。cut -d' ' -f2-
:这个 cut
命令用于从每行中分割出文件路径。因为每行的格式是“时间戳 文件路径”,所以使用空格(-d ' '
)作为分隔符,并取第二个字段到最后(-f2-
),即文件路径。xargs -d '\n' -r rm
:xargs
命令用于从标准输入接收文件路径,并执行 rm
删除这些文件。-d '\n'
指定输入项的分隔符是换行符,-r
表示如果没有输入则不执行任何操作。删除临时文件:
rm "$tmpfile"
这行命令用于在操作完成后删除临时文件,清理脚本运行时产生的临时数据。
整个脚本的设计考虑到了效率和安全性,使用临时文件来处理可能的大量数据,同时确保在异常情况下不会误删除文件或执行未预期的命令。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。