编辑: 为了清楚起见,我们从一个类似于这个的for循环得到了我们的STDOUT
for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
MY_FILE=`find $DIR -type f | head -$i | tail -1`
FILE_TYPE=`file -b "$MY_FILE"
FILE_TYPE_COUNT=`echo $FILE_TYPE" | sort | uniq -c`
echo "$FILE_TYPE_COUNT"
done
因此,我们的STDOUT基本上是从逐个打印的文件实用程序输出的,而不是它实际上是我们可以复制的字符串集 - 这可能是所有问题背后的核心
`
所以有一个泡菜,我绝对不能把头包起来。
基本上我创建了一个shellcript,它将打印出我们目录中的各种文件类型。但是,由于某些奇怪的原因,当我尝试在输出上使用uniq时,它几乎无效。这是我的输出
POSIX shell script, ASCII text executable
ASCII text
Bourne-Again shell script, ASCII text executable
UTF-8 Unicode text, with overstriking
Bourne-Again shell script, ASCII text executable
似乎相当不言自明,但是当我使用
时FILE_TYPE_COUNT=`echo "$FILE_TYPE" | sort | uniq -c`
这是它打印的结果
1 POSIX shell script, ASCII text executable
1 ASCII text
1 Bourne-Again shell script, ASCII text executable
1 UTF-8 Unicode text, with overstriking
1 Bourne-Again shell script, ASCII text executable
显然应该是
1 POSIX shell script, ASCII text executable
1 ASCII text
2 Bourne-Again shell script, ASCII text executable
1 UTF-8 Unicode text, with overstriking
知道我做错了吗?
显然,uniq认为线条并不相同,但我认为这是排序错误,因为它无法对我的STDOUT进行排序。那么任何线索如何正确排序ALPHABETICALlY?
答案 0 :(得分:4)
你的方法看起来过于复杂,试试这个:
find $DIR -type f -exec file -b -- {} \; | sort | uniq -c
如果您不熟悉-exec
,它会在每个文件中执行给定的命令,在我们的情况下为file -b -- {}
。占位符{}
将替换为当前正在处理的文件的路径。
为什么你的方法不起作用:
您在for循环中执行此操作echo $FILE_TYPE" | sort | uniq -c
,$FILE_TYPE
仅包含该点的一个文件的文件类型。您需要将sort | uniq -c
移出循环。
我调整了您的代码以便它可以运行:
declare -a TYPES=()
for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
MY_FILE=`find a/ -type f | head -$i | tail -1`
FILE_TYPE=`file -b "$MY_FILE"`
TYPES+=("$FILE_TYPE") # add type of current file to TYPES array
done
# TYPES now contains the types of all files and we can now count them
printf "%s\n" "${TYPES[@]}" | sort | uniq -c
答案 1 :(得分:1)
您看到的问题是因为您正在为循环的每次迭代排序一个项目的集合。
您需要对循环的整个输出进行排序。
你的(语法修复)脚本:
for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
MY_FILE=`find $DIR -type f | head -$i | tail -1`
FILE_TYPE=`file -b "$MY_FILE"`
FILE_TYPE_COUNT=`echo "$FILE_TYPE" | sort | uniq -c`
echo "$FILE_TYPE_COUNT"
done
Mofified正常工作:
for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
MY_FILE=`find $DIR -type f | head -$i | tail -1`
file -b "$MY_FILE"
done | sort | uniq -c
优化一次:
for FILE in $(find $DIR -type f); do
file -b "$FILE"
done | sort | uniq -c
优化两次(参见@P.Gerber的答案):
find $DIR -type f -exec file -b -- {} \; | sort | uniq -c
你的原始剧本非常低效。
关于效率的说明&amp;操作:
${FILE_AMOUNT}
必须正确迭代整个数据集find
,它会返回整个数据集,然后丢弃您不感兴趣的所有内容,每次迭代 sort
和uniq
答案 2 :(得分:1)
除了其他好的解决方案之外,请务必了解您正在使用的排序规则集。要检查当前的排序规则,您可以执行以下操作:
echo anything | sort --debug
使用注释查看结果。考虑:
echo -e "a 2\na1" | sort --debug
sort: using ‘en_US.UTF-8’ sorting rules
a1
__
a 2
___
请注意,规则集正在排序,可能会出现意外结果。如果您正在寻找简单的字节比较,请务必将LC_ALL=C
设置为:
LC_ALL=C sort
例如:
echo -e "a 2\na1" | LC_ALL=C sort --debug
sort: using simple byte comparison
a 2
___
a1
__
使用LC_ALL
对于获得您期望的结果非常重要。最后,运行locale
命令并阅读手册页以获取特定于语言环境的信息。