我有一个file_id = 840920
,我必须只选择属于的子文件file_id = 840920
。dat 文件的名称不同,但在所有 dat 文件中,父文件 id 可用。记录示例显示如下:
445973129|2602325065|840920|1|RUPATXEM14|LVP|||20180924 18:25:10
445973130|2602325066|840920|2|RP_STG_TEST_WED|LVP|||20180924 18:23
所以我只想将我的搜索映射到第三列并提取那些 dat 文件并将它们复制到不同的文件夹。
下面是我在 unix 中执行相同操作的代码。需要一些帮助来获得更多建议或更好的处理方法。我的问题是,matched_file_id
当我单独运行 while 循环时,我能够打印值,但当我将它们作为代码的一部分包含时,代码不会打印显示matched_file_id
值:有什么建议吗?
cat $TMP/TempBatchData.txt | while read FILE_ID #FILE_ID = 840920
do
for file in *CDI*.dat; do
echo $file >> all_CDI_LIST.txt
done
while IFS= read -r line; do
matched_file_id=`cat $line | cut -f3 -d"|" | sort -u` # echo all the third
column values
done < "all_CDI_LIST.txt"
if [[ $matched_file_id == $FILE_ID ]]; then
echo $line >> final_cdi_list.txt
fi
done
done
答案1
问题、可疑片段:
$matched_file_id
包含零个或多个值,$FILE_ID
只有当有一个值时比较才会成功;$matched_file_id
每 设置一次,每 执行一次与 的line
比较;$FILE_ID
FILE_ID
done
最后有一个额外的内容(?);column values
应该属于一条评论;- 变量没有被引用;
TMP
应该设置。
这是一个重写的过程。它并不完全相同,但方法似乎更好:
TMP="/the/right/path"
find . -type f -name '*CDI*.dat' \
-exec sh -c '
<"$1" cut -f3 -d"|" | grep -qFx -f "$TMP/TempBatchData.txt"
' sh {} \; -print > final_cdi_list.txt
解释:
find
查找与该模式匹配的所有文件*CDI*.dat
。- 对于每个这样的文件,都会运行一个 shell 来处理管道。
cut
提取第三列。grep
quietly (-q
) 检查-F
给定文件 ( ) 中的任何文字字符串 ( )是否存在于整行 ( )-f
的输出中。cut
-x
- 如果是,
find
将打印该文件的路径。
注意事项、差异、怪癖:
find
以递归方式运行。要仅处理当前目录而不处理子目录,您需要-maxdepth 1
(POSIX 不要求)或来自的 POSIX 解决方案这个问题或者让壳膨胀*CDI*.dat
(find *CDI*.dat -type f -exec …
),但这也有其缺点。find
将打印以 为前导的路径./
。要获取基本名称,您需要-printf '%f\n'
(非 POSIX) 而不是-print
或例如-exec basename {} \;
(POSIX 兼容) 而不是-print
。grep -F
匹配文字字符串。在您的代码中,每一行都会$TMP/TempBatchData.txt
经过两次隐式处理:- 与
read FILE_ID
(相对于read -r FILE_ID
) - 在里面
[[ $matched_file_id == $FILE_ID ]]
(比较使用[[
对右侧未加引号的字符串执行模式匹配,而不仅仅是普通的字符串比较)。
我不确定您是否依赖这个。您可能需要调整我的代码。- 与
标题提到将文件复制到另一个目录。使用我的方法,您无需处理即可
final_cdi_list.txt
执行此操作。只需使用-exec cp {} "/another/directory" \;
而不是 即可-print
。
查找匹配文件的全部工作都可以用 sole 来完成grep
,不过你需要调整模式。例如:
grep -l '^[0-9]*|[0-9]*|840920|' *CDI*.dat
一个文件中可以包含许多模式(-f "$TMP/TempBatchData.txt"
),但它们必须像上面那样。如果匹配的文件太多,*CDI*.dat
您将得到“参数列表太长”的结果(for file in *CDI*.dat;
您最初使用的方法不受此影响)。
也许可以调整目录结构(例如,仅*CDI*.dat
当前目录和子目录中的文件、允许递归搜索或根本不允许子目录)和模式文件格式。这个想法是使用
grep -lr -f "$TMP/TempBatchData.txt"
或类似的东西。注意-r
POSIX 不要求这样做,在这个例子中,它的含义来自 GNU grep
:递归读取当前工作目录下的所有文件。
单个grep
过程应该比任何使用find -exec
或read
(并以任何方式匹配字符串)的解决方案更快。