Linux: 管道 `find` 文本文件列表 | `dos2unix` | `dd` 命令

Linux: Pipe `find` text file list | `dos2unix` | `dd` command

我正在尝试做的事情:

find "${TEMPDIR}" -name *.[Tt][Xx][Tt] | /
xargs dos2unix -k | /
dd if=/dev/null of="$_" bs=1 seek=$(echo $(stat --format=%s "$_" ) - $( tail -n1 "$_" | wc -c) | bc )

我无法将 xargs dos2unix -k | / 的 (EDIT output) 文件名传送到第三行,我得到以下错误:

stat: cannot stat '': No such file or directory
tail: cannot open '' for reading: No such file or directory
dd: failed to open '': No such file or directory

显然我错误地认为 "$_" 足以通过管道传递输出。

如何将 xargs dos2unix -k 的输出(文本文件)通过管道传输到第三行 dd if=/dev/null of="$_" bs=1 seek=$(echo $(stat --format=%s "$_" ) - $( tail -n1 "$_" | wc -c) | bc )

第 3 行的解决方案来自 SO 上关于从文件中删除最后一行的另一个问题的答案,这个答案特别被吹捧为大文件的好解决方案:

您可以尝试将 dos2unix 替换为显式替换:

find "${TEMPDIR}" -iname '*.txt' -exec cat {} \; |
tr -d '\r' |
...

由于新行的 windows 是 \r\n,您使用命令 tr.

删除了所有出现的 \r

关于 find 命令,您可以使用选项 -iname 进行不区分大小写的搜索和 -exec 到 运行 命令。

这有帮助吗?

find "${TEMPDIR}" -iname '*.txt' -exec dos2unix "{}" \; -exec sed -i '$d' "{}" \;

如果文件真的很大,你用tr重写它已经搞砸了效率。然后,您使用 tail 第二次阅读它只是为了获取最后一行的索引。

我能想出的最低效的修复方法是用一个执行这两个功能的命令替换 dos2unixdd,这样您只读取和写入输出文件一次。

find "$TMPDIR" -iname '*.txt' -exec perl -i -ne '
    print $line if defined $line; ($line = $_) =~ s/5$//' {} \;

您尝试使用 $_ 作为当前文件名无效。 $_的值是上一个completed命令使用的最后一个文件名;但在管道中间,还没有完成任何事情。一种可能的解决方法(我只是为了说明,而不是作为推荐的解决方案包括在内)是 运行 xargs 中您可以访问 {} 的所有内容,类似于它在 find -exec.

find "$TMPDIR" -iname '*.txt' -print0 |
xargs -r0 sh -c 'dos2unix -k "{}"
    if=/dev/null of="{}" bs=1 seek=$(
        echo $(stat --format=%s "{}" ) - $( tail -n1 "{}" | wc -c) | bc)

我添加了-print0和相应的xargs -0以及xargs -r作为良好形式的说明;虽然以零结尾的文本格式是 GNU find 扩展,但在其他平台上通常找不到。

(私下里,我可能还会用一个简单的 Awk 脚本替换 seek 计算,而不是花费三个过程来执行减法。)