如何将特定目录名称复制到文件

如何将特定目录名称复制到文件

所以我有几个目录,我只想将以“k”开头并以“g”结尾的目录名称复制到文件中。我怎么做?

答案1

zsh

print -rC1 -- k*g(N/) > dirnames.txt

但请注意,由于换行符与文件名中的任何字符一样有效,这意味着您将无法区分名为 和 的两个文件k1gk2g名为 的文件k1g<newline>k2g

您可以通过将选项添加-Nprint.

dirs=( ${(0)"$(<dirnames.nul-delimited)"} )然后,您可以使用或 之类的内容对生成的文件进行后处理xargs -r0a dirnames.nul-delimited some-command

要还包含子目录中找到的文件的名称(基本名称/ tail)k*g,您可以执行以下操作:

print -rNC1 -- **/k*g(ND/:t) > dirnames.nul-delimited

请注意,例如,如果同时存在 aa/king和文件,则它可能会有重复项。.git/king您可以使用以下方法删除重复项:

() { print -rNC1 -- ${(u)argv} > dirnames.nul-delimited; } **/k*g(ND/:t)

获得人类可读且可后处理的文件列表的一种方法是使用 shell 引用文件名:

print -rC1 -- k*g(N/:q) > dirnames.txt

这里使用zsh特定的引用变体。或者使用可移植的(在类似 sh 的 shell 中)和更可靠的引用语法:

() { print -rC1 -- ${(qq)argv} > dirnames.txt; } k*g(N/)

或者使用 GNU ls

ls -Ud --quoting-style=shell-always -- k*g(N/) > dirnames.txt

稍后可以通过以下方式检索该列表:

dirs=( ${(Q)${(zZ[n])"$(<dirnames.txt)"}} )

zsh

或者在两者中zshbash(或 ksh93,如果您dirs首先声明为数组):

eval "dirs=( $(<dirnames.txt) )"

如果您没有或zsh由于某种原因无法使用,但在 GNU 系统上,并且您的文件名是在语言环境中的有效文本上创建的,您可以执行以下操作:

  • 每行打印一个(假设文件名不包含换行符):

    find . -mindepth 1 -maxdepth 1 -name 'k*g' -type d -printf '%f\n' |
      sort > dirnames.txt
    
  • 相同的 NUL 分隔:

    find . -mindepth 1 -maxdepth 1 -name 'k*g' -type d -printf '%f\0' |
      sort -z > dirnames.txt
    
  • 递归,以 null 分隔:

    find . -name 'k*g' -type d -printf '%f\0' |
      sort -z > dirnames.txt
    
  • 相同的重复数据删除:

    find . -name 'k*g' -type d -printf '%f\0' |
      LC_ALL=C sort -zu |
      sort -z > dirnames.txt
    
  • 引用(虽然按批次排序)

    find . -mindepth 1 -maxdepth 1 -name 'k*g' -type d -printf '%f\0' |
      xargs -r0 ls -d --quoting-style=shell-always --
    
  • 引用并正确排序:

    find . -mindepth 1 -maxdepth 1 -name 'k*g' -type d -printf '%f\0' |
      sort -z |
      LC_ALL=C gawk -v 'RS=\0' -v q="'" '
        shquote(s) {
          gsub(q, q "\\" q q, s)
          return q s q
        }
        {print shquote($0)}' |
      xargs -r0 ls -d --quoting-style=shell-always --
    

答案2

可能最好不要使用ls,因为

尝试:

find * -maxdepth 0 -type d -name 'k*g' > filename.txt

(如果没有-maxdepth 0它,也会执行文件夹的子文件夹。如果大写的 K 和 G 也应该计算在内,请使用-iname代替。)-name

如果您有可能拥有以连字符开头的文件夹或文件(但是谁做的?),您可以使用它:

find . -maxdepth 1 -type d -name 'k*g' | sed 's/^\.\///' > filename.txt

-maxdepth 0注意从到 的切换-maxdepth 1

答案3

您可以将 shell 通配符与重定向一起使用:

$ ls -d k*g/ > filename.txt

如果您的目录名称包含换行符,这将会中断。 (我思考它只会选取目录而不是文件,但我不在计算机前进行检查。)

相关内容