File awk检查文件存在

File awk检查文件存在,file,unix,awk,File,Unix,Awk,或 /home/user/.ssh/config\n2015-03-02-存在 /主/用户/桌面/temp328-已删除 我只想打印存在的文件,但此命令不起作用。第二次尝试相当接近;在测试-f之后需要一个空格 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}' 您可能希望使用if(

/home/user/.ssh/config\n2015-03-02-存在

/主/用户/桌面/temp328-已删除


我只想打印存在的文件,但此命令不起作用。

第二次尝试相当接近;在
测试-f
之后需要一个空格

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}'
您可能希望使用
if(system(…)==0)
来获得所需的语义。另外,更为优雅的是,Awk需要大括号之外的条件,因此可以避免显式的
if

base$ echo '2015|/etc/mtab
> 2015|/etc/ntab' | awk -F\| '{ if (system("test -f " $2)) print $2}'
/etc/ntab
同意评论人士的观点,即使用Awk来实现这一点是近乎疯狂的

如注释所示,如果您需要使用完全任意的文件名,则可以添加代码以引用任何shell特殊功能:

awk -F\| 'system("test -f " $2)==0 { print $2 }'
。。。但您的总体解决方案无法处理包含换行符或管道字符的文件名(因为您分别将它们用作记录分隔符和字段分隔符),因此,放弃Awk并使用不同的方法重新开始可能是明智的前进方向

(替换中的字符类是不完整的;有各种标点字符等可以添加,并且我可能缺少一些重要的东西;但是在快速检查时,多余的反斜杠应该是无害的。如果你没有GAWK,请参阅和/或再次考虑放弃这种方法。)

而IFS='|'read-r stuff filename;做
测试-f“$filename”和&echo“$filename”

完成检查awk中是否存在可读文件很容易,而不必借助
system()
生成一些内容。只要试着从文件中读取

从awk的手册页(在我的系统上):

在所有情况下,getline都会为成功的 输入,0表示文件结尾,-1表示错误

所以。一些示例代码

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?
:
使用您的示例数据:

#!/usr/bin/awk -f

function file_exists(file) {
  n=(getline _ < file);
  if (n > 0) {
    print "Found: " file;
    return 1;
  } else if (n == 0) {
    print "Empty: " file;
    return 1;
  } else {
    print "Error: " file;
    return 0;
  }
}

BEGIN {

  file_exists(ARGV[1]);

}
为了更广泛地使用,您可以将此函数缩短为:

$ fmt="2015-03-02|/home/user/.ssh/config\n2015-03-02|/home/user/Desktop/temp328\n"
$ printf "$fmt" | cut -d\| -f2 | xargs -n 1 ./check.awk
Error: /home/user/.ssh/config
Error: /home/user/Desktop/temp328
功能文件\u存在(文件){
如果((getline=0){return 1;}
}

使用GNU awk,您可以使用
filefuncs
扩展名附带的
stat()

function file_exists(file) {
  if ((getline _ < file) >= 0) { return 1; }
}
Awk:

-v file=foo的输出:

$ awk -v file=foo '
@load "filefuncs"
BEGIN {
    ret=stat(file,fdata)
    printf "ret:  %d\nsize: %d\n",ret,fdata["size"]
}'
对于

ret:  0
size: 4
对于不存在的
baz

ret:  0
size: 0

不是我的答案,但这里还没有记录。从“”:

给出了此方法:

ret:  -1
size: 0
这是在
ARGV[i]
中命名的文件上的基本
readline
,当它失败时,他们会删除数组元素。文件不存在或不可读

不管怎样,你都不能用它。都在同一个
aWk
进程中,不执行shell等

我今天需要它,我编写了以下小函数:

   else if ((getline junk < ARGV[i]) < 0) # unreadable
        delete ARGV[i]
      :
##文件#
#*参考:[12.3.3检查可读数据文件](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html#File-检查)
#o[GNU Awk用户指南](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html)
#
函数文件存在(文件路径、rslt、垃圾)
{
_rslt=(0==1)#错误
如果((getline _junk0))35;#可读
{
_rslt=(1==1);
关闭(文件路径);
}
返回_rslt;
}
注:

  • 当文件为空时,函数返回TRUE

您可以使用BASH轻松完成此操作,并将结果馈送/导入AWK

  ##  file_exist
  #     * ref: [12.3.3 Checking for Readable Data Files](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html#File-Checking)
  #         o [The GNU Awk User's Guide](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html)
  #

  function file_exist(  file_path, _rslt, _junk  )
  {
      _rslt = (0==1);     #   false

      if( (getline _junk < file_path) > 0)  )    ## readable 
      {
          _rslt = (1==1);
          close( file_path );
      }
      return _rslt;
  }

有没有明确的原因让你必须使用
awk
?a)这不是awk的工作,而是shell的工作,b)你写的都不是awk语法。编辑您的问题以解释为什么要使用awk进行此操作。这不会告诉您文件是否存在,只会告诉您getline是否可以从中读取一行。如果文件存在且为空或不可读,则将失败。很好,谢谢。我提到了非零长度部分,但我已经更新了措辞,在我的回答中加入了“可读”条件,以及处理“空”情况的改进awk函数。如果
getline
成功,如果文件是二进制文件,并且恰好在前N个字节中没有换行符,它可能会消耗任意大的内存。当然,Perl的
-e
操作符使这一点变得微不足道,但OP询问了awk。如果$2=“file 2”或$2=“filel |*-da”,shell写入错误:/bin/sh:1:l*-da:not found如果需要使用古怪的文件名,则无法确保它们不包含单引号或换行符,则此命令很好。调整代码以应对这些场景并非不可能,但我认为您可能需要重新考虑您的方法。但对于眼前的问题,请在
系统
命令中的文件名周围添加单引号,或者在将文件名传递给
系统
之前,添加代码以反斜杠转义文件名中的所有shell特殊字符,
ret:  -1
size: 0
  # readable.awk --- library file to skip over unreadable files

  BEGIN {
      for (i = 1; i < ARGC; i++) {
          if (ARGV[i] ~ /^[[:alpha:]_][[:alnum:]_]*=.*/ \
              || ARGV[i] == "-" || ARGV[i] == "/dev/stdin")
              continue    # assignment or standard input
          else if ((getline junk < ARGV[i]) < 0) # unreadable
              delete ARGV[i]
          else
              close(ARGV[i])
      }
  }
   else if ((getline junk < ARGV[i]) < 0) # unreadable
        delete ARGV[i]
      :
  ##  file_exist
  #     * ref: [12.3.3 Checking for Readable Data Files](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html#File-Checking)
  #         o [The GNU Awk User's Guide](http://langevin.univ-tln.fr/cours/COMPIL/tps/awk.html)
  #

  function file_exist(  file_path, _rslt, _junk  )
  {
      _rslt = (0==1);     #   false

      if( (getline _junk < file_path) > 0)  )    ## readable 
      {
          _rslt = (1==1);
          close( file_path );
      }
      return _rslt;
  }
% ls
file_list file1 file3
% cat file_list
file1
file2
file3
file4
% cat file_list | bash -c 'while read file ; do [ -f "$file" ] || echo "No file: $file"; done'
No file: file2
No file: file4