printf "2015-03-02|/home/user/.ssh/config\n2015-03-02|/home/user/Desktop/temp328\n" | awk -F\| 'if ( -f $2 ) { print $2}'
Run Code Online (Sandbox Code Playgroud)
或者
printf "2015-03-02|/home/user/.ssh/config\n2015-03-02|/home/user/Desktop/temp328\n" | awk -F\| '{if (system("test -f" $2)) print $2}'
Run Code Online (Sandbox Code Playgroud)
/home/user/.ssh/config\n2015-03-02 - 存在
/home/user/Desktop/temp328 - 已删除
我只想打印存在的文件,但此命令不起作用。
第二次尝试相当接近。后需要一个空格test -f。
base$ echo '2015|/etc/mtab
> 2015|/etc/ntab' | awk -F\| '{ if (system("test -f " $2)) print $2}'
/etc/ntab
Run Code Online (Sandbox Code Playgroud)
您可能想要反转使用if (system(...)==0)来获得您期望的语义。此外,更优雅一点的是,Awk 希望在大括号之外有一个条件,因此您可以避免显式的if.
awk -F\| 'system("test -f " $2)==0 { print $2 }'
Run Code Online (Sandbox Code Playgroud)
同意评论者的意见,即为此使用 awk 是极端的坚果。
如果,如注释中所示,您需要使用完全任意的文件名,您可以添加代码来引用任何 shell 特殊内容:
awk -F\| 'system ("test -f " gensub(/[^\/A-Za-z0-9]/, "\\\\&", "g", $2))==0 {
print $2 }' # caveat: gensub() is gawk only
Run Code Online (Sandbox Code Playgroud)
...但您的整体解决方案无法处理包含换行符或管道符的文件名(因为您分别将它们用作记录和字段分隔符)所以再次放弃 Awk 并使用不同的方法重新开始可能是理智的前进道路。
(替换中的字符类不完整;可以添加各种标点符号等,我可能会遗漏一些重要的东西;但是快速检查一下,多余的反斜杠应该是无害的。如果您没有 Gawk,请参阅在这里和/或再次考虑放弃这种方法。)
while IFS='|' read -r stuff filename; do
test -f "$filename" && echo "$filename"
done <<':'
2015|/etc/mtab
2016|/etc/ntab
2017|/path/to/file with whitespace in name
2018|/path/to/file\with[funny"characters*in(file'name|even pipes, you see?
:
Run Code Online (Sandbox Code Playgroud)
(仍然没有办法换行,但其他一切都应该没问题。)
使用 GNU awk,您可以使用stat()包含在filefuncs扩展中的内容:
$ ls -l
-rw-r--r-- 1 james james 4 Oct 3 12:48 foo
-rw------- 1 root root 0 Oct 3 12:48 bar
Run Code Online (Sandbox Code Playgroud)
awk:
$ awk -v file=foo '
@load "filefuncs"
BEGIN {
ret=stat(file,fdata)
printf "ret: %d\nsize: %d\n",ret,fdata["size"]
}'
Run Code Online (Sandbox Code Playgroud)
输出-v file= foo:
ret: 0
size: 4
Run Code Online (Sandbox Code Playgroud)
为了bar:
ret: 0
size: 0
Run Code Online (Sandbox Code Playgroud)
对于不存在的baz:
ret: -1
size: 0
Run Code Online (Sandbox Code Playgroud)