xargs ожидает очень особый формат ввода, в котором аргументы разделяются пробелами или символами новой строки (иногда другими формами вертикального пробела, иногда зависящими от текущей локали), и где одинарные кавычки, двойные кавычки и обратный слеш могут использоваться для их экранирования (но в другом путь из кавычек оболочки).
-l1не для передачи одной строки ввода в качестве единственного аргумента mkdir, а для вызова одного mkdirвызова для каждой отдельной строки ввода, но со словами в этой строке, которые по-прежнему выделяются в качестве различных аргументов mkdir.
Реализация GNU xargsдобавила -0возможность десятилетия назад принимать входные данные, разделенные NUL. Это наиболее очевидный способ отделить слова, которые в конечном итоге станут аргументами команды, потому что символ NUL оказывается единственным символом, который не может встречаться в аргументе команды или имени файла (выбранный формат списка, в котором по одному файлу в строке не может представлять все возможные имена файлов, так как не допускает новую строку в имени файла).
Это -0было скопировано несколькими другими xargsреализациями, но не всеми.
С тем, что вы можете сделать:
<file tr '\n' '\0' | xargs -0 mkdir -p --
Это будет вызывать mkdirкак можно меньше раз с максимально возможным количеством аргументов.
Но обратите внимание, что если fileон пуст, mkdirон все равно будет запущен, и вы получите синтаксическую ошибку mkdirиз-за отсутствующего аргумента. GNU xargsдобавил -rопцию для того, что было скопировано несколькими другими реализациями.
GNU xargsтакже добавил (позже) -dвозможность указывать произвольные разделители, но я не думаю, что какая-либо другая реализация скопировала его. С GNU xargsлучший способ:
xargs -rd '\n' -a file mkdir -p --
Передавая файл с -a(также расширением GNU) вместо stdin, это означает, что mkdirstdin сохраняется.
POSIXly, вам нужно будет постобработать ввод, чтобы поместить его в ожидаемый формат xargs. Вы можете сделать это, например, с:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --
Где мы заключаем каждую строку в двойные кавычки и экранируем каждую, "как "\""перед передачей в xargs.
Но остерегайтесь возможных ограничений:
- ошибка, когда файл пуст уже упомянутый выше
- может произойти сбой в некоторых реализациях (включая of
sed), если содержимое fileне является допустимым текстом в текущей локали. Если fileимена файлов кодируются более чем в одной другой кодировке, или кодировка, отличная от локали, вы можете исправить локаль на C, что должно помочь.
- некоторые
xargsреализации имеют смехотворно низкие ограничения на максимальную длину аргумента (может быть до 255 байт).
Чтобы обойти синтаксическую ошибку при пустой ошибке ввода , вы можете написать:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh
-dварианта.