Самое длинное имя файла в большой директории

В большой директории моей системы Ubuntu (> 140000 файлов и> 200 подкаталогов) я знаю, что где-то есть два файла с длинными именами для копирования в папку Windows (NTFS). Я попробовал и получил два сообщения об ошибках, но я не обратил внимания на то, что вложенные папки были в них.

Как найти два файла с самыми длинными именами?

3
задан 1 July 2017 в 01:34

6 ответов

Я думаю, что решение @ steeldriver - лучший выбор, но вот мое альтернативное решение, вы можете использовать комбинации команд, чтобы найти ровно два (или более) имени файла.

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

выход будет выглядеть так:

length ./path/to/file

Вот реальный пример:

42 ./path/to/this-file-got-42-character-right-here.txt
31 ./path/to/this-file-got-31-character.txt

Примечания

find дает нам список всех файлов в этом каталоге, таких как:

./path/to/this-file-got-31-character.txt

, используя awk, мы добавляем длину файла для начала каждой строки (это точно длина файла, а не путь):

31 ./path/to/this-file-got-31-character.txt

, наконец, мы сортируем его на основе длины файла и получаем первые две строки, используя head.

4
ответ дан 22 May 2018 в 20:59

Я думаю, что решение @ steeldriver - лучший выбор, но вот мое альтернативное решение, вы можете использовать комбинации команд, чтобы найти ровно два (или более) имени файла.

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

выход будет выглядеть так:

length ./path/to/file

Вот реальный пример:

42 ./path/to/this-file-got-42-character-right-here.txt 31 ./path/to/this-file-got-31-character.txt

Примечания

find дает нам список всех файлов в этом каталоге, таких как:

./path/to/this-file-got-31-character.txt

, используя awk, мы добавляем длину файла для начала каждой строки (это точно длина файла, а не путь):

31 ./path/to/this-file-got-31-character.txt

, наконец, мы сортируем его на основе длины файла и получаем первые две строки, используя head.

4
ответ дан 18 July 2018 в 10:51

Я думаю, что решение @ steeldriver - лучший выбор, но вот мое альтернативное решение, вы можете использовать комбинации команд, чтобы найти ровно два (или более) имени файла.

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

выход будет выглядеть так:

length ./path/to/file

Вот реальный пример:

42 ./path/to/this-file-got-42-character-right-here.txt 31 ./path/to/this-file-got-31-character.txt

Примечания

find дает нам список всех файлов в этом каталоге, таких как:

./path/to/this-file-got-31-character.txt

, используя awk, мы добавляем длину файла для начала каждой строки (это точно длина файла, а не путь):

31 ./path/to/this-file-got-31-character.txt

, наконец, мы сортируем его на основе длины файла и получаем первые две строки, используя head.

4
ответ дан 24 July 2018 в 19:39

Основываясь на комментариях, то, что вам действительно нужно в этом случае, это список всех файлов, имена которых длиннее некоторого максимального количества символов, и, к счастью, это относительно легко с использованием регулярного выражения find:

find $PWD -regextype posix-extended -regex '.*[^/]{255,}$'

Для такого большого количества файлов и каталогов вы, вероятно, захотите избежать сортировки - вместо этого давайте просто сохраним текущую запись самых длинных и вторых самых длинных имен файлов и их полные пути:

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];
  }'

или с 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];
  }'
3
ответ дан 22 May 2018 в 20:59
  • 1
    Ницца ... это было простое «найти макс». вопрос: D – Ravexina 1 July 2017 в 20:49
  • 2
    Спасибо steeldriver. Я изо всех сил стараюсь быть справедливым здесь - ваше первое решение в комментариях («найти очень длинные имена файлов»), хотя и не является строго ответом на мой вопрос, сработало хорошо, и этого было достаточно для того, что мне было нужно в тот момент. Тем не менее, сообщение @ Ravexina («найти два самых последних имени файла») содержит точный ответ на мой вопрос. Поэтому я отметил ответ Равешины как принятый и поддержал оба. – Jos 1 July 2017 в 22:35

Основываясь на комментариях, то, что вам действительно нужно в этом случае, это список всех файлов, имена которых длиннее некоторого максимального количества символов, и, к счастью, это относительно легко с использованием регулярного выражения find:

find $PWD -regextype posix-extended -regex '.*[^/]{255,}$'

Для такого большого количества файлов и каталогов вы, вероятно, захотите избежать сортировки - вместо этого давайте просто сохраним текущую запись самых длинных и вторых самых длинных имен файлов и их полные пути:

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]; }'

или с 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]; }'
3
ответ дан 18 July 2018 в 10:51

Основываясь на комментариях, то, что вам действительно нужно в этом случае, это список всех файлов, имена которых длиннее некоторого максимального количества символов, и, к счастью, это относительно легко с использованием регулярного выражения find:

find $PWD -regextype posix-extended -regex '.*[^/]{255,}$'

Для такого большого количества файлов и каталогов вы, вероятно, захотите избежать сортировки - вместо этого давайте просто сохраним текущую запись самых длинных и вторых самых длинных имен файлов и их полные пути:

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]; }'

или с 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]; }'
3
ответ дан 24 July 2018 в 19:39
  • 1
    Ницца ... это было простое «найти макс». вопрос: D – Ravexina 1 July 2017 в 20:49
  • 2
    Спасибо steeldriver. Я изо всех сил стараюсь быть справедливым здесь - ваше первое решение в комментариях («найти очень длинные имена файлов»), хотя и не является строго ответом на мой вопрос, сработало хорошо, и этого было достаточно для того, что мне было нужно в тот момент. Тем не менее, сообщение @ Ravexina («найти два самых последних имени файла») содержит точный ответ на мой вопрос. Поэтому я отметил ответ Равешины как принятый и поддержал оба. – Jos 1 July 2017 в 22:35

Другие вопросы по тегам:

Похожие вопросы: