我执行ls
这样的命令来列出多个目录。请注意文件夹中的空白区域X y
。
ls -1d 2021*/"X y"/foobar
输出是
'20211121-161518-801/X y/foobar'
'20211128-151513-585/X y/foobar'
'20211130-170001-724/X y/foobar'
看来ls这里还是用了引号。但是当我将此输出与xargs
引号结合使用时,接缝就会丢失
ls: Zugriff auf '20211121-161518-801/X' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'y/foobar' nicht möglich: Datei oder Verzeichnis nicht gefunden
xargs命令是这样的
ls -1d 2021*/"X y"/foobar | xargs ls
最后我会使用 axargs rm -rf
但这xargs ls
只是一个测试。
答案1
虽然 Stéphane Chazelas 为您提供了总体上相当不错且深入的“现代”探索ls
,但并非所有的ls
es 都是一样的。即使新的 GNUls
将会出现,--zero
也需要几十年的时间才能普及到所有地方,而且这仍然不适用于所有系统,尤其是非基于 GNU 的系统。
普遍的共识是ls
,它是供人类消费的,不应该真正被信任用于其他任何用途。
尽管这是老年管理员中相当普遍的知识,但新手和新手管理员由于许多可以理解的(和其他无法解释的)原因仍然只被ls
.随着 Linux 超越小众市场并进入越来越主流和民族化的环境,这种ls
热爱正在成为严重的问题(正如您自己的情况所证明的那样)。这也是为什么 GNU正在“快速”发展几十年来任何人都应该拥有的ls
选择。ls
但是,如果您确实想立即可靠、安全地解决这个问题,并且正确地完成这项工作,那么正确的工具就是find
命令:要么用作零分隔列表生成器,要么用作直接命令执行器。
用作find
零分隔列表生成器:
find topdir -mindepth 1 [-maxdepth 2] -type d -print0 | xargs -0 -I@ stat @
find
作为直接执行者使用:
find topdir -mindepth 1 [-maxdepth 2] -type d -exec stat '{}' \;
使用-mindpeth
/-maxdepth
您可以控制下降的深度find
,并-type
控制它将处理哪些对象。您还可以匹配对象名称甚至对象路径。因为find
默认情况下不会以任何“智能”方式破坏或转义对象名称,所以您可以通过管道(生成器)或作为 argv 向量(执行器)的一部分,毫无恐惧地将这些 anmes 传递给原始对象。
请记住,当以这种方式通过管道对列表进行排序时,-print0
必须始终使用,以便名称以零分隔,并且其他字符(例如空格和换行符)可以直接表达,并且不会混淆读者。
答案2
的 GNU 实现ls
有一个--quoting-style
选项,可以让您指定引用样式,但它们都不与 期望的引用样式兼容xargs
。
xargs
(由 PWB Unix 在 70 年代末引入)引用风格类似于 Mashey shell(也来自 PWB Unix),后者是 Bourne shell 的前身。
ls --quoting-style=shell-always
按照 Bourne/POSIX shell 样式使用单引号进行引号,单引号本身输入为\'
.除了反斜杠之外,xargs
还支持'...'
和 ,"..."
但引用的字符串不能包含只能用反斜杠转义的换行符。
POSIXxargs
规范还期望xargs
将输入解析为当前语言环境中的文本,并且也不保证它适用于大于 256 字节的参数,因此通常不能用于处理任意数据。
真正唯一可靠的使用方法xargs
是使用-0
某些实现中的选项,例如 GNU xargs
(您通常也想使用该-r
选项,也是非标准的)。
GNU 的下一个版本ls
将有一个--zero
选项来输出 NUL 分隔的文件,因此您将能够执行以下操作:
ls -t --zero | xargs -r0 printf ' * %s\n'
例如。
现在,您可以做的是使用--quoting-style=shell-always
模式将该列表传递给 shell,然后该 shell 将其转换为 NUL 分隔列表:
(
echo 'files=('
ls --quoting-style=shell-always -t
echo '); print -rNC1 -- $files'
) | zsh | xargs -r0 some command
但是,如果您已经在使用zsh
,那么您实际上并不需要ls
,也xargs
可以zsh
按照其他条件对其全局进行排序,例如ls
和 具有用于stat
检索文件元数据的内置函数(您可能想要使用 的唯一原因ls
)及其自己的zargs
命令。
无论如何,在:
ls -d -- *.txt
*.txt
它是扩展到匹配文件列表的shell 。ls
在那里非常无用,因为它最终只是打印它们。
您也可以将 glob 扩展传递给可以打印 NUL 分隔列表的东西,例如print
内置的zsh
:
print -rNC1 -- *.txt(N)
(这里还使用N
ullglob 限定符,因此如果 glob 与任何文件都不匹配,它不会打印任何内容)。
或者在bash
shell 中(有时仍然在 GNU 系统上使用,因为那是 GNU shell):
print0() {
[ "$#" -eq 0 ] || printf '%s\0' "$@"
}
shopt -s nullglob
print0 *.txt