编辑:要明确,我们得到了我们从一个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
因此,我们的标准输出基本上是从印刷逐个文件实用程序输出,而不是将其actualling被设置字符串,我们可以复制 - 这很可能是后面的所有问题的核心
`
所以这是一个泡菜我绝对不能换我的头周围。
基本上我创建一个shell脚本,将打印出我们在我们的目录中的文件类型不同。 它几乎工程,但是,当我尝试对我的输出使用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的认为线是没有什么不同,但是这就是我认为什么是排序的过错,因为它不能排序我的标准输出。 因此,任何线索,如何正确地按字母顺序排序列表?
你的做法似乎过于复杂,试试这个:
find $DIR -type f -exec file -b -- {} \; | sort | uniq -c
如果找你不熟悉-exec
,它执行给定的命令,在我们的案例file -b -- {}
每个文件一次。 占位符{}
被替换的路径当前正被处理的文件。
为什么你的做法不工作:
你这样做echo $FILE_TYPE" | sort | uniq -c
中的for循环, $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
你所看到的问题是因为你选了一组一个项目,为循环的每个迭代。
你需要循环的整体输出,而不是进行排序。
你(语法固定)脚本:
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格柏的答案。):
find $DIR -type f -exec file -b -- {} \; | sort | uniq -c
您的原始脚本是惊人,效率低下。
效率和操作的注意事项:
-
${FILE_AMOUNT}
必须正确遍历整个数据集 - 您正在运行
find
,它返回整个数据集,然后丢弃你不感兴趣, 每次迭代的一切 - 您正在运行
sort
和uniq
,在每个迭代上,对大小为一的数据集 - 当你不断地重新计算你的数据集,如果通过你的脚本执行改变半路上(例如:文件/目录中创建/删除),那么你的成绩将无效
- 请记住,每次开始一个新的程序时,你付出性能上的损失 - 这是事实,你不断地计算你的数据集,然后丢弃“你不想要的一切”加剧
在这里除了其他好的解决办法,一定要明白,你所使用的排序规则集。 检查你当前的排序规则,你可以这样做:
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
指挥和阅读man页面以获取特定区域设置信息。