大目录中最长的文件名

Jos*_*Jos 5 command-line bash

在我的 Ubuntu 系统上的一个大目录(> 140000 个文件和> 200 个子目录)中,我知道某处有两个文件名太长而无法复制到 Windows (NTFS) 文件夹。我试过了,收到了两条错误消息,但我没有注意文件所在的子文件夹。

如何找到名称最长的两个文件?

Rav*_*ina 6

我猜@steeldriver 的解决方案是一个更好的选择,但这是我的替代解决方案,您可以使用命令组合来准确地找到两个(或更多)最长的文件名。

find . | awk 'function base(f){sub(".*/", "", f); return f;} \
{print length(base($0)), $0}'| sort -nr | head -2
Run Code Online (Sandbox Code Playgroud)

输出将是这样的:

length ./path/to/file
Run Code Online (Sandbox Code Playgroud)

这是一个真实的例子:

42 ./path/to/this-file-got-42-character-right-here.txt
31 ./path/to/this-file-got-31-character.txt
Run Code Online (Sandbox Code Playgroud)

笔记

find 为我们提供了该目录中所有文件的列表,例如:

./path/to/this-file-got-31-character.txt
Run Code Online (Sandbox Code Playgroud)

使用awk我们将文件长度添加到每一行的开头(这正是文件长度而不是路径的长度):

31 ./path/to/this-file-got-31-character.txt
Run Code Online (Sandbox Code Playgroud)

最后我们根据文件长度对其进行排序,并使用head.


ste*_*ver 5

根据评论,在这种情况下,您真正​​需要的是名称长于最大字符数的所有文件的列表 - 幸运的是,使用正则表达式相对find容易

find $PWD -regextype posix-extended -regex '.*[^/]{255,}$'
Run Code Online (Sandbox Code Playgroud)

对于如此大量的文件和目录,您可能希望避免排序 - 相反,让我们只保留最长和第二长文件名及其完整路径名的运行记录:

find $PWD -printf '%p\0' | awk -v RS='\0' '
  {
    # get the length of the basename of the current filepath
    n = split($0,a,"/");
    currlen = length(a[n]);

    if (currlen > l[1]) {
      # bump the current longest to 2nd place
      l[2] = l[1]; p[2] = p[1];
      # store the new 1st place length and pathname
      l[1] = currlen; p[1] = $0;
    }
    else if (currlen > l[2]) {
      # store the new 2st place length and pathname
      l[2] = currlen; p[2] = $0;
    }
  }

  END {
      for (i in l) printf "(%d) %d : %s\n", i, l[i], p[i];
  }'
Run Code Online (Sandbox Code Playgroud)

或使用 GNU awk(支持 2D 数组)

$ find $PWD -printf '%p\0' | gawk -v RS='\0' '
  {
    # get the length of the basename of the current filepath
    n = split($0,a,"/");
    currlen = length(a[n]);

    if (currlen > p[1][1]) {
      # bump the current longest to 2nd place
      p[2][1] = p[1][1]; p[2][2] = p[1][2];
      # store the new 1st place length and pathname
      p[1][1] = currlen; p[1][2] = $0;
    }
    else if (currlen > p[2][1]) {
      # store the new 2st place length and pathname
      p[2][1] = currlen; p[2][2] = $0;
    }
  }

  END {
      for (i in p[1]) printf "(%d) %d : %s\n", i, p[i][1], p[i][2];
  }'
Run Code Online (Sandbox Code Playgroud)