首页 > 解决方案 > 将“/”附加到目录末尾

问题描述

完全是菜鸟问题,但是,使用 ls 管道到 grep,我需要查找名称中包含所有大写字母的文件或目录,并且目录需要附加“/”以表示它是一个目录。试图附加“/”是我唯一坚持的部分。再次,我为业余问题道歉。我目前有ls | grep [A-Z],示例应该是:BIRD, DOG, DOGDIR/

标签: unix

解决方案


这是一个有趣的问题,因为用 bash 单线来完成这件事有点困难。

这就是我想出的。它看起来不是很优雅,但我不知道如何改进。

find /animals -type d -or -type f \
| grep '/[A-Z]*$' \
| xargs -I + bash -c 'echo -n $(basename +)$( test -d + && echo -n /),\\ ' \
| sed -e 's/, *$//'; echo

我会为你分解

  1. find /animals -type d -or -type f每行一次写出它在 /animals 中找到的目录和文件(请参阅下面的测试环境 dockerfile - 我创建了 /animals 以匹配您想要的输出)。据我所知,Find 无法进行正则表达式匹配,所以......

  2. grep '/[A-Z]*$'过滤器的find输出,以便只显示路径,其中文件或目录名称的最后一部分,在最后的 / 之后,都是大写的

  3. xargs -I + bash -c '...'当您在 shell 中并且想要使用“for”循环时,您应该使用的是xargs. 学习它,知道它,爱它。 xargs获取它的输入,默认情况下由 分隔$IFS,并运行您为每条输入提供的命令。所以这将为每个路径运行一个 bash shell。通过了 grep 过滤器。在我的情况下,-I +xargs用其当前输入文件名替换文字“+”字符。 -I也让它一次通过一个xargs。有关详细信息,请参阅xargs手册页。

  4. 'echo -n $(basename +)$( test -d + && echo -n /),\\ '这是将为通过xargs的每个路径运行的内部 bash 脚本grep

    1. basename +将目录组件从路径中删除;从您不想要的示例输出中,例如/animals/DOGDIR/,您想要DOGDIR/basename是为我们修剪目录的程序。

    2. test -d + && echo -n /检查+(记住 xargs 将用文件名替换它)是否是目录,如果是,则运行echo -n /. echo的-n参数抑制换行符,这对于以您指定的 CSV 格式获取输出很重要。

    现在我们可以把它们放在一起,看看我们是,附加echo -n的输出,如果它是一个目录,然后附加到那个目录。所有s 都运行以抑制换行符以保持输出 CSV 的外观。 basename +/,echo-n

  5. | sed -e 's/, *$//'; echo纯粹是为了格式化。添加,到每个单独的输出是获取 CSV 的一种简单方法,但它,在列表末尾留给我们一个 final。到目前为止,sed调用删除,了输出末尾的任意数量的空格 - 例如,所有 xargs 调用的整个输出。而且由于我们从未在该输出的末尾输出换行符,因此最终echo添加了该内容。

通常在 unix shell 中,您可能不需要 CSV 样式的输出。在大多数情况下,您可能想要一个换行符分隔的输出,每行一个匹配的文件,这会更简单一些,因为您不需要所有这些花哨的东西-n,使其成为 CSV 样式。但是,如果需要,有效的要求。

FROM debian
RUN mkdir -p /animals
WORKDIR /animals
RUN mkdir -p DOGDIR lowerdir && touch DOGDIR/DOG DOGDIR/lowerDOG2 lowerdir/BIRD
ENTRYPOINT [ "/bin/bash" ]
CMD [ "-c" , "find /animals -type d -or -type f | grep '/[A-Z]*$'| xargs -I + bash -c 'echo -n $(basename +)$( test -d + && echo -n /),\\ ' | sed -e 's/, *$//'; echo"]
$ docker run --rm test
BIRD, DOGDIR/, DOG

推荐阅读