[英]directories based on the filename and then move the associated files to the correct directories for random name
[英]Sorting files into directories based on their name
我有一些包含很多文件的目录。 随着其中一些文件接近60万个文件,它们已成为处理的主要难题。 仅列出文件正逐渐成为处理文件的应用程序中的主要瓶颈。
文件的命名如下:id_date1_date2.gz我已决定将文件分成几个较小的文件,具体取决于第一部分“ id”。
由于相同的ID可能显示在大量文件中,并且相同的ID已经显示在多个目录中,因此我需要跟踪已复制的文件ID,以及从哪些目录复制。 否则,我最终会进行相同的复制,而复制的次数是疯狂的,或者如果从目录Y复制过来的话,如果从目录Z复制了,则会丢失idX。
我已经编写了一个脚本来完成此任务。 包括一些调试
#!/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}'
。
在循环中调用外部可执行文件会使事情减慢很多,尤其是一次只处理一个值(或数据行)的情况。 commands that I mentioned are examples of this. Also, your
的'sed commands that I mentioned are examples of this. Also, your
commands that I mentioned are examples of this. Also, your
awk`命令可能能够转换为参数扩展形式。
GNU find
具有正则表达式功能,可以代替grep
使用。
所有包含文件名的变量名都应加引号。
cp的-n选项在这种情况下非常有用。 它使您不必担心文件是否已在目标位置中。
-n, --no-clobber
do not overwrite an existing file (overrides
a previous -i option)
基本上,这样一来,您谈论两次重复进行相同工作的情况就会消失。 您可以将关注点分为移动所有文件和仅移动之前从未移动过的文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.