Цитировать документация gawk(добавлено примечание):
Any additional arguments on the command line are normally treated as input files to be processed in the order specified. However, an argument that has the form var=value, assigns the value value to the variable var—it does not specify a file at all.
Почему команда останавливается и ждет? Поскольку в формеawk 'processing_script_here' my=file.txt
нет файла, указанного по приведенному выше определению,-my=file.txt
интерпретируется как присвоение переменной, и если файл не определен, awk
будет читать стандартный ввод (, что также видно из strace
, который показывает, что awk в такой команде ожидает системного вызова read(0,'...)
.
Это также задокументировано в спецификациях POSIX awk ,см. раздел ОПЕРАНДЫ и назначения часть этого)
Присвоение переменной очевидно в awk '{print foo}' foo=bar /etc/passwd
, где значение foo
печатается для каждой строки в /etc/passwd. Однако указание ./foo=bar
или полного пути работает.
Обратите внимание, что запуск strace
на awk '1' foo=bar
, а также проверка с помощью cat foo=bar
показывают, что это проблема, специфичная для awk -, и execve показывает имя файла в качестве переданного аргумента, поэтому оболочки не имеют ничего общего с переменной env. задания в этом случае.
Кроме того, обратите внимание, что awk '...script...' foo=bar
не приведет к созданию переменной среды оболочкой, поскольку назначение переменной среды должно предшествовать команде, чтобы она вступила в силу. См. Правила грамматики оболочки POSIX , пункт номер 7. Кроме того, это можно проверить с помощьюawk '{print ENVIRON["foo"]}' foo=bar /etc/passwd
Вы можете передать (должным образом отсортированный )список имен файлов через uniq -d
. Предполагая, что ваша оболочка и uniq
имеют одинаковые представления о порядке сортировки, например
printf -- "%s\n" * | cut -c1-8 | uniq -d
Если результат не -пустой, должны быть дубликаты. Обернув это в команду find
:
find. -type d -exec sh -c '
cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"
' find-sh {} \; -print
Так дано
$ tree.
.
├── subdir1
│ └── 20200403foo
├── subdir2
│ ├── 20200403bar
│ └── 20200403foo
├── subdir3
│ └── 20200403foo
├── subdir4
│ ├── 20200403bar
│ └── 20200403foo
└── subdir5
└── 20200403foo
5 directories, 7 files
, затем
$ find. -type d -exec sh -c 'cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"' find-sh {} \; -print
./subdir4
./subdir2
Если вам нужно обрабатывать имена файлов, содержащие символы новой строки, а ваши cut
и uniq
поддерживают нулевые разделители, вы можете изменить конвейер на
printf "./%s\0" * | cut -zc1-10 | uniq -zd
Портативное решение, которое также правильно обрабатывает произвольные пути к файлам, в том числе содержащие символы новой строки, за счет некоторой степени неэлегантности и медлительности:
find /path/to/dir -type d \( -exec sh -c '
cd "$1"
printf "%s/" [0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]* \
| awk -v RS="/" "seen[substr(\$0,1,8)]++ { exit 1 }"
' mysh {} \; -o -print \)
find
используется для рекурсивного поиска каталогов в /path/to/dir
и в каждом найденном каталоге выполняется сценарий, который передает имена файлов, соответствующие шаблону, примерно напоминающему дату (предполагается формат гггг/мм/дд ), каждый из которых завершается символом /
, в экземпляр awk
, который читает/
-отдельных записей и завершает работу со статусом 1
, как только повторяется восьмисимвольный -символ (, начиная с первая строка )найдена во входных данных, в результате чего имя каталога будет -print
ed.
Более быстрая альтернатива, основанная на инструментах GNU:
find /path/to/dir -type f -name '[0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]*' \
-print0 | awk -v FS='/' -v OFS='/' -v RS='\0' '
{ file=substr($NF,1,8); $NF=""; dir=$0 }
seen[dir file]++ { dupl[dir] }
END { for (d in dupl) print d }'
Здесь в /path/to/dir
рекурсивно ищутся только обычные файлы, имя которых (примерно )начинается с даты. Найденные пути к файлам передаются в awk
в виде потока записей, разделенных NUL -. Для каждой записи сохраняются только первые восемь символов последнего компонента (имени файла ), а результирующий путь сохраняется в ассоциативном массиве. При обнаружении дубликата распечатывается часть каталога (, т. е. путь с удаленным компонентом имени файла ).