【问题标题】:How to properly grep filenames only from ls -al如何仅从 ls -al 正确 grep 文件名
【发布时间】:2012-03-22 12:27:00
【问题描述】:

当我通过 ls 管道时,如何告诉 grep 仅在“文件名”匹配的情况下打印行?我希望它忽略每一行上的所有内容,直到时间戳之后。必须有一些简单的方法可以在单个命令上执行此操作。

如您所见,如果没有它,如果我搜索文件“rwx”,它不仅会返回包含 rwx.c 的行,还会返回前三行,因为权限。我打算使用 AWK,但如果我搜索“rwx”,我希望它显示整个最后一行。

有什么想法吗?

编辑:感谢下面的黑客攻击。但是,最好有一个更无错误的方法。例如,如果我有一个名为“rob rob”的文件,我将无法使用所述解决方案。

drwxrwxr-x 2 rob rob  4096 2012-03-04 18:03 .
drwxrwxr-x 4 rob rob  4096 2012-03-04 12:38 ..
-rwxrwxr-x 1 rob rob 13783 2012-03-04 18:03 a.out
-rw-rw-r-- 1 rob rob  4294 2012-03-04 18:02 function1.c
-rw-rw-r-- 1 rob rob   273 2012-03-04 12:54 function1.c~
-rw-rw-r-- 1 rob rob    16 2012-03-04 18:02 rwx.c
-rw-rw-r-- 1 rob rob    16 2012-03-04 18:02 rob rob

【问题讨论】:

  • 如果只想要文件名,不要使用ls -al;使用普通的ls -a 获取有趣的名称,然后使用ls -ld 获取它们的详细信息?解析ls 的输出是出了名的困难,即使在您尝试考虑包含空格的文件名之前也是如此。好消息:即使日期格式发生变化,时间中的列数仍保持不变(两个空格分隔的值)。
  • 我同意乔纳森的观点;如果您要做的只是列出文件,则将正确的选项传递给 ls。
  • 实际上,我对日期列的评论并不完全准确;您的 ls -l 显示两列;我的最近文件显示三个:-r--r--r-- 1 jleffler staff 26676 Mar 3 21:44 ccs.nmd 和旧文件-r--r--r-- 1 jleffler staff 6510 Mar 17 2003 README,v

标签: unix grep ls


【解决方案1】:

以下将仅列出文件名,每行一个文件。

$ ls -1     

包括 .文件

$ ls -1a 

请注意,参数是数字“1”,而不是字母“l”。

【讨论】:

  • 这不涉及问题的 grep 部分。
【解决方案2】:

你为什么不使用grep并匹配时间戳后面的文件名?

grep -P "[0-9]{2}:[0-9]{2} $FILENAME(\.[a-zA-Z0-9]+)?$"

[0-9]{2}:[0-9]{2} 是暂时的,$FILENAME 是您放置 rob robrwx 的位置,而结尾的 (\.[a-zA-Z0-9]+)? 是允许可选扩展名。

编辑:下面的@JonathanLeffler 指出,当文件超过 6 个月时,时间列会被替换为一年 - 无论如何,这就是我的计算机上发生的情况。您可以使用([0-9]{2}:[0-9]{2}|(19|20)[0-9]{2}) 来留出时间或年份,但您最好使用 awk (?)。

[foo@bar ~/tmp]$ls -al
total 8
drwxrwxr-x  2 foo foo 4096 Mar  5 09:30 .
drwxr-xr-- 83 foo foo 4096 Mar  5 09:30 ..
-rw-rw-r--  1 foo foo    0 Mar  5 09:30 foo foo
-rw-rw-r--  1 foo foo    0 Mar  5 09:29 rwx.c
-rw-rw-r--  1 foo foo    0 Mar  5 09:29 tmp

[foo@bar ~/tmp]$export filename='foo foo'

[foo@bar ~/tmp]$echo $filename
foo foo

[foo@bar ~/tmp]$ls -al | grep -P "[0-9]{2}:[0-9]{2} $filename(\.[a-zA-Z0-9]+)?$"
-rw-rw-r--  1 cha66i cha66i    0 Mar  5 09:30 foo foo

(如果需要,您还可以扩展为匹配整行:

^                              # start of line
[d-]([r-][w-][x-]){3} +        # permissions & space (note: is there a 't' or 's'
                               # sometimes where the 'd' can be??)
[0-9]+                         # whatever that number is
[\w-]+ [\w-]+ +                # user/group (are spaces allowed in these?)
[0-9]+ +                       # file size (modify for -h switch??)
(19|20)[0-9]{2}-               # yyyy (modify if you want to allow <1900)
(1[012]|0[1-9])-               # mm
(0[1-9]|[12][0-9]|3[012]) +    # dd
([01][0-9]|2[0-3]):[0-6][0-9] +# HH:MM (24hr)
$filename(\.[a-zA-Z0-9]+)?     # filename & optional extension
$                              # end of line

。你明白了,根据你的需要量身定做。)

【讨论】:

  • 当心旧文件 - ls -l 列表中的时间格式在文件超过 6 个月大时丢失时间并获得年份。
  • :感谢您的接机。我注意到我的日期格式也与 OP 不同 - 希望对于给定的机器保持足够恒定?
【解决方案3】:

假设您不准备这样做:

ls -ld $(ls -a | grep rwx)

那么您需要利用在文件名开始之前有 8 列以空格分隔的事实。使用egrep(或grep -E),你可以这样做:

ls -al | egrep "^([^ ]+ +){8}.*rwx"

这会在第 8 列之后查找“rwx”。如果您希望名称以 rwx 开头,请省略 .*。如果您希望名称以 rwx 结尾,请在末尾添加 $。请注意,我使用了双引号,因此您可以插入一个变量来代替文字 rwx

这是在 Mac OS X 10.7.3 上测试的; ls -l 命令始终为日期字段提供三列:

-r--r--r--  1 jleffler  staff   6510 Mar 17  2003 README,v
-r--r--r--  1 jleffler  staff  26676 Mar  3 21:44 ccs.nmd

您的ls -l 似乎只给出了两列,因此您需要将您的机器的{8} 更改为{7} - 并注意在系统之间迁移。

【讨论】:

    【解决方案4】:

    好吧,如果你正在使用其中没有空格的文件名,你可以这样做:

    grep 'rwx\S*$'
    

    【讨论】:

    • 这到底是做什么的?有空格的文件名的替代品吗?
    • 它匹配“rwx 后跟任意数量的非空格字符后跟行尾”。对于带有空格的文件名并没有一个很好的替代方案,因为这样就无法区分时间和文件名之间的中断与文件名的一部分。
    【解决方案5】:

    除了 frrm 之外,您可以使用 ls、exaple ksh 和 bash 的模式匹配, 这可能是您应该做的,您可以使用文件名出现在 固定位置。 awk(gawk、nawk 或任何你有的)是一个更好的选择。 如果你必须使用 grep,它对我来说就像家庭作业。请这样标记它。

    假设文件名的起始位置基于 linux 中 ls -l 的输出:56

    -rwxr-xr-x  1 Administrators None    2052 Feb 28 20:29 vote2012.txt
    
    ls -l | awk ' substr($0,56) ~/your pattern even with spaces goes here/'
    

    例如,

    ls -l | awk ' substr($0,56) ~/^val/'
    

    将查找以“val”开头的文件

    【讨论】:

      【解决方案6】:

      作为一个简单的技巧,只需在您的文件名前添加一个空格,这样您就不会匹配输出的开头:

      ls -al | grep '\srwx'
      

      编辑:好的,这并不像应有的那么健壮。这是awk:

      ls -l | awk ' $9 ~ /rwx/ { print $0 }'
      

      【讨论】:

      • 但这会获取一个名为def 的文件,该文件由rwx(用户或组)拥有。除非您在模式中指定“abc”,否则它不会获取文件abcrwx
      • 关于用户和组的要点。我想这里确实需要一个适当的正则表达式。
      【解决方案7】:

      这对我有用,不像某些人指出的 ls -l 和其他人。我喜欢这个,因为它非常通用 & 给了我基本文件名,它删除了文件之前的路径名。

      ls -1 /path_name |awk -F/ '{print $NF}'
      

      【讨论】:

        【解决方案8】:

        你只需要一个命令 --

        ls -al | gawk '{print $9}'
        

        【讨论】:

          【解决方案9】:

          你可以用这个:

          ls -p | grep -v / 
          

          【讨论】:

          • 虽然这段代码可以回答问题,但最好包含一些上下文,解释如何它的工作原理和何时 i> 使用它。从长远来看,纯代码的答案没有用处。
          【解决方案10】:

          这是超级旧的,但我需要答案并且很难找到它。我并不真正关心单线部分;我只是需要它完成。这很糟糕而且很脏,需要您计算列数。我不是在这里寻求支持,只是为未来的搜索者留下一些选择。

          有用的 awk 技巧是 here -- 使用 awk 打印从第 n 到最后的所有列

          如果 YOUR_FILENAME="rob rob"WHERE_FILENAMES_START=8

          ls -al | while read x; do
            y=$(echo "$x" | awk '{for(i=$WHERE_FILENAMES_START; i<=NF; ++i) printf $i""FS; print ""}')
            [[ "$YOUR_FILENAME " = "$y" ]] && echo "$x"
          done
          

          如果您将其保存为 bash 脚本并用 $2 和 $1 替换 vars,将脚本放入您的 usr bin 中...然后您将拥有干净简单的单线;)

          输出将是:

          > -rw-rw-r-- 1 rob rob    16 2012-03-04 18:02 rob rob
          

          问题是单线所以...

          ls -al | while read x; do [[ "$YOUR_FILENAME " = "$(echo "$x" | awk '{for(i=WHERE_FILENAMES_START; i<=NF; ++i) printf $i""FS; print ""}')" ]] && echo "$x" ; done
          

          (哈哈;P)


          另一方面:mathical.coffee your answer 是 rad。它没有解决我的这个问题的版本,所以我没有投票,但我喜欢你的正则表达式分解:D

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-24
            • 1970-01-01
            相关资源
            最近更新 更多