我在一个文件夹中有一些文件,我想以表格方式在一个 file.txt 中打印它们的名称,就像文本不是一个下一个一样,是否有任何命令可以实现这一点?
dd1.txt dd2.txt dd3.txt dd5.txt
答案1
假设不需要递归到子目录:
printf '%s\n' * | paste -d ' ' -s - >other/path/file.txt
这将在文件的一行中列出当前目录中的所有可见文件名other/path/file.txt
。
我选择写入其他目录中的文件,因为写入file.txt
当前目录将使该文件名成为输出的一部分。显然,首先确保输出文件名可以自由使用。
该printf
实用程序通常是 shell 中的内置实用程序,因此即使*
可能扩展到数千个名称(请注意printf
,不是sh
尽管是 OpenBSD 中或OpenBSD 上的内置实用程序ksh
)。该实用程序每行生成一个文件名,但不会干扰名称本身的格式,这ls
在某些情况下可能会发生。
该paste
命令采用换行符分隔的名称列表,并将它们放在一行上,中间有空格。-d
如果需要,可以使用该选项轻松更改分隔符。
这将无法正确处理带有嵌入换行符的文件名,也无法从生成的列表中提取带有嵌入空格的文件名。
答案2
$ files=(*)
$ echo "${files[@]}"
dd1.txt dd2.txt dd3.txt dd5.txt
答案3
要使用 shell 打印当前目录中非隐藏文件的名称(按词法排序、以空格字符分隔并以换行符结尾),zsh
您可以执行以下操作:
print -r - *(N)
或者:
echo -E - *(N)
带壳fish
:
set files *; echo -E -- $files
带壳ksh93
:
print -r - ~(N)*
带壳yash
:
(set -o nullglob; ECHO_STYLE=raw echo *)
对于bash
、 和 ,前提是posix
和xpg_echo
选项未同时启用(在 的某些部署中默认情况下bash
):
(shopt -s nullglob; set -- *; echo -En "$@"$'\n')
或者:
POSIXly(因此也可以在 bash(即使不在 POSIX 模式下)和 zsh(但仅在 POSIX 模式下)中工作):
set -- [*] *
case "$1$2" in
('[*]*') printf '\n';;
(*)
printf %s "$2"
shift 2
printf ' %s' "$@"
esac
printf '\n'
(请记住,printf
如果当前工作目录中有大量文件,则在非内置 shell 实现中可能会失败)。
请注意,如果当前工作目录不包含非隐藏文件或不可读,所有这些都将打印空行。在任何情况下,如果没有文件名包含换行符,则输出将仅包含一行。
令人惊讶的是,使用标准 shell 来完成如此简单的任务竟然如此困难,但这里我们必须解决 Unix shell 和实用程序的一些错误设计:
- 该
echo
命令(用于输出由空格分隔的参数的命令)是最难移植的命令之一,并且标准实现以一种无法轻易禁用的方式完成超出所需的工作。 - 许多 shell(包括 POSIX sh 规范)在不匹配时会保留未展开的 glob。
- that
ls
是列出文件的命令,没有任何方法以可后处理的格式生成该列表。 - 该线不能包含任何任意的字节序列(这是大多数系统上文本行表示的情况,但不限于 Unix,更不用说 Unix 实用程序了)。