gpt4 book ai didi

linux - 根据文件名将文件分类到目录中

转载 作者:太空狗 更新时间:2023-10-29 12:38:19 24 4
gpt4 key购买 nike

我有几个包含很多文件的目录。由于其中一些接近 600k 文件,它们已成为处理起来的一大难题。仅列出文件正在慢慢成为处理它们的应用程序的主要瓶颈。

文件的命名方式如下:id_date1_date2.gz我决定根据第一部分“id”将文件分成几个较小的文件。

由于相同的 id 可能会出现在大量文件中,并且相同的 id 已经出现在多个目录中,所以我需要跟踪哪些文件 id 已被复制,以及从哪些目录复制。否则,如果已经从目录 Z 复制,我最终会重复同样的复制操作,或者在从目录 Y 复制时丢失 id X。

我已经写了一个脚本来完成这个。包括一些调试

#!/bin/bash  
find /marketdata -maxdepth 2 -type d | grep "[0-9]\.[0-9][0-9][0-9]$" | sort | #head -n2 | tail -n1 |
while read baseDir; do

cd $baseDir;
echo $baseDir > tmpFile;
find . -type f | grep -v "\.\/\." | #sort | head -n4 |
while read file; do
name=$(awk 'BEGIN {print substr("'"$file"'", 3,index("'"$file"'", "_")-3 )}');

dirkey=${baseDir//[\/,.]/_}"_"$name;
if [ "${copied[$dirkey]}" != "true" ]; then
echo "Copying $baseDir/$name with:";
echo mkdir -p $(sed 's/data/data4/' tmpFile)/$name;
#mkdir -p $(sed 's/data/data4/' tmpFile)/$name;
oldName=$baseDir/$name"_*";
echo cp $oldName "$(sed 's/data/data4/' tmpFile)/$name/";
#cp $oldName "$(sed 's/data/data4/' tmpFile)/$name/";
echo "Setting $dirkey to true";
copied[$dirkey]="true";
else
echo "$dirkey: ${copied[$dirkey]}"
sleep 1
fi
done;

rm tmpFile;
done

这里的问题是复制的所有键的值似乎从第一次复制开始就变为真,所以我对 bash 数组的处理可能是这里的问题。

一些进展:我尝试将每个键写入一个文件,并且在每次迭代时,我将该文件读入一个数组。这显然非常丑陋,但看起来它实现了我的目标。可能是因为我已经处理了几千个 ID,所以这变得非常慢。稍后更新。

对于将来可能会发现此内容的其他人,这是最终脚本:

declare -A copied

find /marketdata -maxdepth 2 -type d -name "[0-9]\.[0-9][0-9][0-9]" | sort | #head -n3 | tail -n1 |
while read baseDir; do

cd $baseDir;
find . -type f | grep -v "\.\/\." | sort | #head -n100 |
while read file; do
length=$(expr index "$file" "_");
name=${file:2:$((length - 3))};

dirkey=${baseDir//[\/,.]/_}"_"$name;
if [ "${copied[$dirkey]}" != "true" ]; then
echo "Copying ${baseDir}/${name} to ${baseDir//data/data4}/$name";
mkdir -p "${baseDir//data/data4}/$name";
oldName="${baseDir}/${name}_*";
cp -n $oldName "${baseDir//data/data4}/${name}/";
copied[$dirkey]="true";
fi
done;
done

没有 awk,没有 sed,更好的引用,没有将临时文件写入磁盘,更少的 grep。我不确定关联数组是否正常工作是否需要 dirkey hack,我也不完全理解为什么我需要 oldName var。

最佳答案

如果 $dirkey 中的值包含字母字符,您将不得不使用 Bash 4 之前不可用的关联数组。如果您使用的是 Bash 4 并且键是字母数字而不是除了简单的数字,在脚本顶部添加以下内容:

declare -A copied

补充说明:

您在某些地方使用了参数扩展,而在其他地方使用了 sed。您可以在(也许)所有情况下使用大括号扩展。

我建议不要像 $var"literal"$var 这样引用,而是像 "${var}literal${var}" 或者在某些情况下如果文字不会被歧义解释为变量名的一部分,您可以省略大括号:"literal$var"

使用 awk 传递变量而不是复杂的 "'" 引用:awk -v awkvar=$shellvar '{print awkvar}' .

在循环中调用外部可执行文件会大大降低速度,尤其是一次只处理一个值(或一行数据)时。我提到的 'sed 命令就是这方面的例子。此外,您的 awk` 命令可能能够转换为参数扩展形式。

GNU find 有一个正则表达式功能,您可以使用它来代替 grep

所有包含文件名的变量名都应该被引用。

关于linux - 根据文件名将文件分类到目录中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3864904/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com