目录全天都会收到大量文件。我只想根据第 2 行的内容选择并移动文件。第 2 行如下所示:
L054 EL621306DEM-A0-AGI378-0001 70807 201708072017081100061542364673600268
- 条件 1:第 8 列和第 9 列 = EL
- 条件 2:第 42/43/44/45 列 = 2017
(ksh
在 AIX 7.1 上使用)
答案1
使用 GNU 工具(GNU shell 或其他支持 ksh 的 shell)流程替代( <(...)
)、GNUxargs
或类似 FreeBSD 的兼容 (for -a
, -r
, -0
)、GNU mv
for -t
、GNU awk
for nextfile
(也受其他一些实现的支持;在不支持的情况下它将被忽略,但效率较低):
xargs -r0a <(
find dir -type f -exec awk 'FNR == 2 {
if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
printf "%s\0", FILENAME
nextfile}' {} +) echo mv -it /somewhere
echo
(如果高兴就删除)
在非 GNU 系统上,您可以将其更改为:
{
find dir -type f -exec awk -v q="'" '
function quote_for_xargs(s) {
gsub(q, q "\\" q q, s)
gsub("\n", q "\\\n" q, s)
return q s q
}
FNR == 2 {
if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
print quote_for_xargs(FILENAME)
nextfile
}' {} + | xargs sh -c '
[ "$#" -eq 0 ] || exec echo mv -i "$@" /somewhere <&3 3<&-' sh
} 3<&0
(如果高兴就删除echo
)。
也就是说,每个文本文件都有find
调用。awk
在 中awk
,对于每个文件的第二行 ( FNR==2
),如果满足条件,则打印文件名是适合的格式xargs
(xargs 输入被视为由空格或换行符分隔的单词列表,其中单引号和双引号以及反斜杠可用于转义分隔符或彼此)。例如,一个名为 的文件./That's tough.log
将输出为'./That'\''s tough.log'
.
xargs
接受该输入以将尽可能多的参数传递给sh
.我们需要sh
包装器,因为目标目录必须是最后一个参数。我们确实希望这样做,-i
因为由于文件最终位于同一目录中,因此如果移动不同目录中具有相同名称的两个文件,则可能会丢失数据。我们确实需要mv
的 stdin (用于-i
提示)不是是来自 的管道find
,因此使用临时 fd 3 将外部标准输入转发到sh
forsh
来设置mv
其上的标准输入。