根据 bash 中的扩展名高效移动一百万个文件
Effeciantly moving half a million files based on extention in bash
场景:
随着 Locky 病毒的肆虐,我工作的计算机中心发现唯一的文件恢复方法是使用像 Recuva 这样的工具,现在的问题是它将所有恢复的文件转储到一个目录中。我想根据文件扩展名将所有这些文件移动到类别中。所有 JPG 都在一个中,所有 BMP 都在另一个中......等等。我环顾了 Whosebug,并根据各种其他问题和响应,我设法构建了一个小的 bash 脚本(提供的示例),它有点这样做,但是它需要永远完成,我想我的扩展搞砸了。
代码:
#!/bin/bash
path= # Starting path to the directory of the junk files
var=0 # How many records were processed
SECONDS=0 # reset the clock so we can time the event
clear
echo "Searching for file types and then moving all files into grouped folders."
# Only want to move Files from first level as Directories are ok were they are
for FILE in `find -maxdepth 1 -type f`
do
# Split the EXT off for the directory name using AWK
DIR=$(awk -F. '{print $NF}' <<<"$FILE")
# DEBUG ONLY
# echo "Moving file: $FILE into directory $DIR"
# Make a directory in our path then Move that file into the directory
mkdir -p "$DIR"
mv "$FILE" "$DIR"
((var++))
done
echo "$var Files found and orginized in:"
echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds."
问题:
如何在处理 500,000 多个文件时提高效率?查找需要永远获取文件列表,并在循环中尝试创建目录(即使该路径已经存在)。如果可能的话,我想更有效地处理循环的这两个特定方面。
任何 bash 脚本的瓶颈通常是您启动的外部进程的数量。在这种情况下,您可以大大减少对 mv
的调用次数,方法是认识到您要移动的大部分文件都具有 jpg
等通用后缀。从这些文件开始.
for ext in jpg mp3; do
mkdir -p "$ext"
# For simplicity, I'll assume your mv command supports the -t option
find "" -maxdepth 1 -name "*.$ext" -exec mv -t "$ext" {} +
done
使用 -exec mv -t "$ext" {} +
意味着 find
将尽可能多的文件传递给每个对 mv
的调用。对于每个分机,这意味着 一次 次呼叫 find
和最少数量的呼叫 mv
.
移动这些文件后,然后您可以开始一次分析一个文件。
for f in ""/*; do
ext=${f##*.}
# Probably more efficient to check in-shell if the directory
# already exists than to start a new process to make the check
# for you.
[[ -d $ext ]] || mkdir "$ext"
mv "$f" "$ext"
done
权衡发生在决定你想做多少工作之前识别公共扩展以最小化第二个 for
循环的迭代次数。
场景:
随着 Locky 病毒的肆虐,我工作的计算机中心发现唯一的文件恢复方法是使用像 Recuva 这样的工具,现在的问题是它将所有恢复的文件转储到一个目录中。我想根据文件扩展名将所有这些文件移动到类别中。所有 JPG 都在一个中,所有 BMP 都在另一个中......等等。我环顾了 Whosebug,并根据各种其他问题和响应,我设法构建了一个小的 bash 脚本(提供的示例),它有点这样做,但是它需要永远完成,我想我的扩展搞砸了。
代码:
#!/bin/bash
path= # Starting path to the directory of the junk files
var=0 # How many records were processed
SECONDS=0 # reset the clock so we can time the event
clear
echo "Searching for file types and then moving all files into grouped folders."
# Only want to move Files from first level as Directories are ok were they are
for FILE in `find -maxdepth 1 -type f`
do
# Split the EXT off for the directory name using AWK
DIR=$(awk -F. '{print $NF}' <<<"$FILE")
# DEBUG ONLY
# echo "Moving file: $FILE into directory $DIR"
# Make a directory in our path then Move that file into the directory
mkdir -p "$DIR"
mv "$FILE" "$DIR"
((var++))
done
echo "$var Files found and orginized in:"
echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds."
问题:
如何在处理 500,000 多个文件时提高效率?查找需要永远获取文件列表,并在循环中尝试创建目录(即使该路径已经存在)。如果可能的话,我想更有效地处理循环的这两个特定方面。
任何 bash 脚本的瓶颈通常是您启动的外部进程的数量。在这种情况下,您可以大大减少对 mv
的调用次数,方法是认识到您要移动的大部分文件都具有 jpg
等通用后缀。从这些文件开始.
for ext in jpg mp3; do
mkdir -p "$ext"
# For simplicity, I'll assume your mv command supports the -t option
find "" -maxdepth 1 -name "*.$ext" -exec mv -t "$ext" {} +
done
使用 -exec mv -t "$ext" {} +
意味着 find
将尽可能多的文件传递给每个对 mv
的调用。对于每个分机,这意味着 一次 次呼叫 find
和最少数量的呼叫 mv
.
移动这些文件后,然后您可以开始一次分析一个文件。
for f in ""/*; do
ext=${f##*.}
# Probably more efficient to check in-shell if the directory
# already exists than to start a new process to make the check
# for you.
[[ -d $ext ]] || mkdir "$ext"
mv "$f" "$ext"
done
权衡发生在决定你想做多少工作之前识别公共扩展以最小化第二个 for
循环的迭代次数。