Одним из вариантов было бы установить нужные имена файлов в качестве текущих аргументов оболочки, а затем попросить printf
напечатать их парами:
set -- *
printf '%s %s\n' "$@" > output
или только определенные файлы:
set -- *_R?.fastq
Порядок зависит от раскрытия подстановочного знака, который вы использовали. Если вы хотите больше контролировать последовательность, вы можете как-то вручную разделить глоб, например:
set -- Paleo*.fastq Vegan*.fastq Omnivore*.fastq FastFood*.fastq
Если да
strace mail <dest> <.
вы можете увидеть, что произошло (хотя вам придется присмотреться ). В системе Linux (, как отмечается в комментарии, другие системы Unix могут вести себя иначе, если чтение каталога завершилось успешно ), имеется около 200 строк вывода, большая часть которых инициализируется, но есть три очень важных строки, в моем случае строки 153, 165 и 191:
...
read(0, 0x556829edb730, 8192) = -1 EISDIR (Is a directory)
...
write(1, "No message, no subject; hope tha"..., 39No message, no subject; hope that's ok) = 39
...
write(4, "Date: Sat, 10 Oct 2020 23:19:22 "..., 212) = 212
...
exit_group(0) = ?
+++ exited with 0 +++
IOW, он попытался прочитать файловый дескриптор 0 (из своего стандартного ввода )и получил ошибку EISDIR
:, потому что оболочка перенаправила .
, т.е. текущий каталог в качестве стандартного ввода, а read
не является разрешено читать каталог. Но почтовая программа проигнорировала эту ошибку, написала сообщение в своем файловом дескрипторе 1 )stdout (о том, что не было ни сообщения, ни темы, переданной ей, и что она надеялась, что все в порядке, а затем приступила к составлению почтового сообщения. и записать его в файловый дескриптор 4, который предположительно каким-то образом подключен для отправки сообщения (сообщение состоит из 212 символов ). Также обратите внимание, что программа завершается со статусом 0 (нормальный выход ).
Если вы попробуете то же самое с cat
или tr
, как предлагает @thanasisp в своем ответе, вы увидите немного другой результат. Эти программы по-прежнему пытаются читать из файлового дескриптора 0 и получают ошибку EISDIR -, но они НЕ игнорируют ошибку; вместо этого они выходят с сообщением об ошибке и не -нулевым статусом:
$ strace cat <.
...
read(0, 0x7fc27daec000, 131072) = -1 EISDIR (Is a directory)
write(2, "cat: ", 5cat: ) = 5
write(2, "-", 1-) = 1
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Is a directory", 16: Is a directory) = 16
write(2, "\n", 1
) = 1
munmap(0x7fc27daeb000, 139264) = 0
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(1) = ?
+++ exited with 1 +++
Но нет никакой разницы в том, как обрабатывается <.
:в обоих случаях оболочка связывает файл (текущий каталог )с файловым дескриптором 0 (стандартный ввод )исполняемую программу. Но программы по-разному реагируют на ошибку. Это все.
Кстати,ответ @thanasisp является точным -и отвечает на большинство ваших вопросов (, даже если он немного скрывает тонкую разницу между командой mail
и, например,. tr
или cat
, на чем я сосредоточусь в этом ответе ).
Точка обозначает текущий каталог, вы можете видеть, что в типичных обычных командах, таких как find.
, cp path/filename.
и т. д., это означает «здесь». Также точка является синонимом команды source
, вы можете увидеть это, набрав man.
.
В вашем случае точка используется как текущий каталог, потому что этот синтаксис:
command < path/to/something
— это перенаправление на стандартный ввод команды, как вы можете видеть в руководстве bash , а этот синтаксис:
command < path/to/something argument
то же, что и выше, только с одним дополнительным аргументом, то же самое:
command argument < path/to/something
Итак, в вашем случае echo
не жалуется, потому что он вообще не читает свой стандартный ввод, читает только следующую строку и печатает ее.
Это лучше видно с другими командами, например tr
, которая читает только стандартный ввод:
tr <. 'a' 'b' # or tr 'a' 'b' <.
tr: read error: Is a directory
tr < file 'a' 'b' # works.