我正在尝试创建一个小脚本,它将获取文件名,然后按大小对该列表进行排序,并对该列表执行命令。到目前为止我有:
#!/bin/bash
filenames="one \
two \
three"
for i in $filenames; do
...
done
它有效,但我想在点击 for 命令之前按文件大小对列表进行排序。
答案1
如果您的文件名不包含任何换行符并且您的系统具有 GNU stat
,您可以:
- 使用数组变量
filenames
- 用于
stat
打印每个文件的大小和文件名,然后使用sort
结果(反向数字),然后删除第一个字段(大小)以cut
获取按大小排序的文件名(最大的在前)。 - 将结果送入
while
循环以进行进一步处理。
filenames=( one two three )
while IFS= read -r file; do
echo "do something with $file"
done < <(stat --printf '%s\t%n\n' -- "${filenames[@]}" | sort -nr | cut -f2-)
与上面相同,但使用空字符作为分隔符(如果你不能保证你的文件名不包含换行符;你还需要 GNUsort
和 GNU cut
):
filenames=( one two three )
while IFS= read -r -d $'\0' file; do
printf 'do something with %s\n' "$file"
done < <(stat --printf '%s\t%n\0' -- "${filenames[@]}" | sort -znr | cut -zf2-)
请注意,对于类型的文件名符号链接,所考虑的是链接本身的大小(而不是它指向的文件的大小)。添加-L
选项来stat
更改它。
请注意,它不适用于名为 as 的文件-
,stat
将其解释为在标准输入上打开的文件。使用./-
来解决它。
答案2
与zsh
,方法相同这是关于按 mtime 排序的类似问题的答案,本身改编自那个,根据任意顺序对数组进行排序(有关详细信息,请参阅后一个):
zmodload zsh/stat
array=(one two three...)
# store sizes in an "A"ssociative array:
typeset -A size
stat -nL -A size +size -- $array
# sort using the oe glob qualifier "n"umerically
sorted_array=(/(e['reply=($array)']noe['REPLY=$size[$REPLY]'])