![](/img/trans.png)
[英]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.