如何结合xargs使“ls -1”在引号中打印出来?

如何结合xargs使“ls -1”在引号中打印出来?

我执行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,但并非所有的lses 都是一样的。即使新的 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)

(这里还使用Nullglob 限定符,因此如果 glob 与任何文件都不匹配,它不会打印任何内容)。

或者在bashshell 中(有时仍然在 GNU 系统上使用,因为那是 GNU shell):

print0() {
  [ "$#" -eq 0 ] || printf '%s\0' "$@"
}
shopt -s nullglob
print0 *.txt

相关内容