如何在bash脚本中进行查找和printf工作 [英] How to make find and printf works in bash script

查看:81
本文介绍了如何在bash脚本中进行查找和printf工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的环境:Linux Redhat,Bash 3.5

My environment: Linux Redhat, Bash 3.5

我创建了一个bash脚本,以使用以下脚本列出子目录中的所有文件.

I have created a bash script to list all of files in sub directories using script below.

#!/bin/bash
for i in $( find . -maxdepth 1 -mindepth 1 -type d ); do
    b=$(echo $i | awk '{print substr($1,3); }' )
    find $i -type f > $i/$b.txt
done

我想在脚本中添加sha1sum,如下所示进行编辑.

I want to add sha1sum to my script, I've edit it as shown below.

#!/bin/bash
for i in $( find . -maxdepth 1 -mindepth 1 -type d ); do
    b=$(echo $i | awk '{print substr($1,3); }' )
    find $i -type f ! -iname '*thumbs.db*' -printf "%b:" -exec sha1sum -b {} \; > ./$i/$b.txt
done

第二个代码失败,并显示以下错误

The second code is failed with error below

No such file or directory

推荐答案

由于您未指定尝试失败的方式[请参见下面的注释1],因此我只是提供了一些有关如何解决基础问题的想法为每个目录生成校验和列表的问题.

Since you don't specify in what way your attempt failed [See note 1, below], I've just provided some thoughts about how to solve the underlying question of producing lists of checksums for each directory.

使用find既不必要又不安全(如果存在任何名称包含空格或shell元字符的目录.

Your use of find is both unnecessary and unsafe (if there are any directories whose names include whitespace or shell metacharacters.

例如,

$( find . -maxdepth 1 -mindepth 1 -type d )

与"glob"大致相同

is roughly the same as the "glob"

./*/

,除了glob不在单个目录上执行路径名扩展或单词拆分外.此外,您可以使用glob */,它将避免使用您显然不希望使用的./前缀.

except that the glob does not perform pathname expansion or word-splitting on the individual directories. Furthermore, you could use the glob */, which will avoid the ./ prefix, which you evidently don't want.

b=$(echo $i | awk '{print substr($1,3); }' )

可以写得更简单

b=${i:3}   # Bash substring notation

b=${i#./}  # Posix standard prefix deletion

但是,如上所述,您可以使用glob,从而避免了任何必须删除前缀的情况.

But, as noted above, you could use a glob and thereby avoid any having to remove the prefix.

所以您可以简单地写:

#!/bin/bash
for b in */; do
    find "$b" -type f > "$b/$b.txt"
done

请注意变量扩展名周围的引号.如果确实需要%b格式来打印文件名,则绝对需要引用扩展名,以避免空格和外壳元字符出现问题,但是无论如何,您都应该养成引用变量扩展名的习惯.

Note the quotes around the variable expansions. If you really need the %b format to print filenames, then you definitely need to quote the expansions to avoid problems with whitespace and shell metacharacters, but anyway you should develop the a habit of quoting variable expansions.

这会产生与脚本稍有不同的输出,因为它不会将./放在输出文件中每一行的开头,但是如果您确实希望可以使用find "./$b" ....

That will produce a slightly different output than your script since it doesn't place the ./ at the beginning of each line in the output file, but if you really wanted that you could use find "./$b" ....

我不明白为什么您会觉得需要使用printf输出SHA-1校验和的文件名,因为sha1sum已经打印了文件名.的确,它是在校验和之后而不是在校验和之后执行的.实际上,这种行为有一个很好的理由:由于无法知道文件名可能包含哪些字符,因此将校验和放在第一位可以更轻松地解析输出.

I don't understand why you feel the need to use printf to output the filename for the SHA-1 checksums, because sha1sum already prints the filename. It's true that it does so after the checksum instead of before. There is actually a good reason for that behaviour: since there is no way of knowing what characters the filename might include, putting the checksum first makes it easier to parse the output.

请注意,在sha1sum的输出中,每个名称包含反斜杠或换行符的文件的输出,校验和行将以反斜杠开头,文件名中的反斜杠和换行符将转义.这样产生的效果与使用%b格式打印f的效果有些相似.

Note that in the output of sha1sum, the output for each file whose name includes a backslash or newline, the checksum line will start with a backslash and the backslash and newline characters in the filename will be escaped. This produces an effect somewhat similar to that of using the %b format to printf.

如果您真的想取消订单,则可以使用awk轻松完成:

If you really want to turn the order around, you can do so easily enough with awk:

#!/bin/bash
for b in */; do
    find "$b" -type f '!' -iname '*thumbs.db*' -exec sha1sum {} + |
    awk '{print "$2:$1"}' > "$b/$b.txt"
done

使用+而不是;终止-exec选项,使find使用文件名列表而不是单个文件名执行命令,这样效率更高.

Using + instead of ; to terminate the -exec option lets find execute the command with a list of filenames instead of just a single filename, which is much more efficient.

  1. 请参阅堆栈溢出帮助页面,我引述如下:

寻求调试帮助的问题(此代码为什么不起作用?")必须包括所需的行为,特定的问题或错误以及在问题本身中再现该错误所需的最短代码.没有明确问题说明的问题对其他读者没有帮助.

Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers.

无效"不是特定问题或错误".您应该始终包含错误消息的文字文本,或者清楚说明程序结果如何未能达到您的期望.

"It doesn't work" is not a "specific problem or error". You should always include the literal text of the error message or a clear statement of how the result of the program failed to meet your expectations.

这篇关于如何在bash脚本中进行查找和printf工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆