Linux: 管道 `find` 文本文件列表 | `dos2unix` | `dd` 命令
Linux: Pipe `find` text file list | `dos2unix` | `dd` command
我正在尝试做的事情:
- 第 1 行:找到任何 .txt 或 .TXT 文件并将它们通过管道传输到下一个命令
- 第 2 行:将 .txt 文件转换为 unix 格式(去掉 Windows 行结尾)
- 第 3 行:删除文件的最后一行,该行始终为空白
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
第二次阅读它只是为了获取最后一行的索引。
我能想出的最低效的修复方法是用一个执行这两个功能的命令替换 dos2unix
和 dd
,这样您只读取和写入输出文件一次。
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
计算,而不是花费三个过程来执行减法。)
我正在尝试做的事情:
- 第 1 行:找到任何 .txt 或 .TXT 文件并将它们通过管道传输到下一个命令
- 第 2 行:将 .txt 文件转换为 unix 格式(去掉 Windows 行结尾)
- 第 3 行:删除文件的最后一行,该行始终为空白
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
第二次阅读它只是为了获取最后一行的索引。
我能想出的最低效的修复方法是用一个执行这两个功能的命令替换 dos2unix
和 dd
,这样您只读取和写入输出文件一次。
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
计算,而不是花费三个过程来执行减法。)