编辑:为了清楚起见,我们从一个执行如下的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基本上是从逐个打印的文件实用程序中输出的,而不是实际上是我们可以复制的字符串集--这很可能是所有问题背后的核心。
`
所以有个泡菜我绝对不能把头绕着。
基本上,我正在创建一个print脚本,它将打印出我们目录中的各种文件类型。但是,由于一些奇怪的原因,当我试图在输出中使用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呢?
发布于 2017-03-19 21:01:41
您的方法似乎过于复杂,请尝试如下:
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发布于 2017-03-19 21:09:22
您所看到的问题是,您正在为循环的每一次迭代排序一组项。
您需要对循环的整个输出进行排序。
您的(语法固定的)脚本:
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经适当调整后,可正常工作:
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你原来的剧本效率太低了。
关于效率和运作的说明:
${FILE_AMOUNT}必须正确地遍历整个数据集。find,它返回整个数据集,然后丢弃您不感兴趣的所有内容,每次迭代sort和uniq。发布于 2017-03-19 22:01:26
除了这里的其他好解决方案之外,一定要理解您正在使用的排序规则集。要检查当前的排序规则,可以执行以下操作:
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命令并读取手册页以获取特定于地区的信息。
https://stackoverflow.com/questions/42891893
复制相似问题