我搜索过这个功能,有很多答案,但我找不到任何适合我的东西。
我有一个包含大约 30,000 个文件的文件夹,我需要一个终端命令或 bash 脚本将这些文件移动到不同的文件夹中。每个文件夹大约有 3000 个文件。某些文件名包含下划线、空格和连字符,因此该命令应该允许我移动这些文件以及不带下划线、空格和连字符的文件。这些文件是 .jpg,但我想要一个可以针对任何文件类型和文件数量进行自定义的命令,以防我将来需要将其用于不同的格式和数量。
更新:
我找到了一个可以满足我需求的 bash 脚本。它将把文件夹中的文件移动到子文件夹中。它适用于任何类型的文件。数字“3001”代表您要移动到每个子文件夹的文件数。这个数字是可以改变的。因此,如果您有一个包含 20000 个文件的文件夹,并且希望将 20000 个文件分成 500 个批次并移动到子文件夹,那么您可以将“3001”替换为“500”。您还可以修改脚本以仅移动特定文件类型,例如:要仅移动 .jpg 文件,请将“for file in *”更改为“for jpg_file in *.jpg”。还将“$file”更改为“$jpg_file”。
#!/bin/bash
c=1; d=1; mkdir -p dir_${d}
for file in *
do
if [ $c -eq 3001 ]
then
d=$(( d + 1 )); c=0; mkdir -p dir_${d}
fi
mv "$file" dir_${d}/
c=$(( c + 1 ))
done
答案1
我尝试了所有脚本,但由于某种原因它们都不起作用,或者只部分起作用。我找到这个bash脚本并对其进行调整以查找 .jpg 文件而不是 .xml 文件:
#!/bin/bash
c=1; d=1; mkdir -p dir_${d}
for jpg_file in *.jpg
do
if [ $c -eq 501 ]
then
d=$(( d + 1 )); c=0; mkdir -p dir_${d}
fi
mv "$jpg_file" dir_${d}/
c=$(( c + 1 ))
done
它运作良好且快速。现在我唯一的问题是让它将任何文件移动到文件夹中,而不仅仅是“.jpg”。它还区分大小写,并且不会移动“.JPG”。有关如何调整它以移动任何文件或至少移动任何图像文件的任何想法?
答案2
怎么样:
for letter in {A..Z}; do
dir=/path/to/sorted/directories/$letter
mkdir $dir
mv "${letter}*.jpg" $dir/
done
当然,还有使用小写字母的相同循环{a..z}
,除非在这种情况下您不想创建单独的小写目录。然后移动线变为:
mv "${letter}*.jpg" ${dir^^}/
用于${var^^}
创建变量的大写版本需要 Bash 4.0。
编辑:修复了缺失的报价。感谢 G-man 指出这一点。
答案3
我想是这样的:
#!/bin/bash
shopt -s nullglob
for i in <directory>; do
mv *.jpg "$dir"
done
这会将所有 jpeg 移动到您需要设置的 $dir,或者您需要使用目录名称创建一个数组。您可以通过切换*.jpg
到任何不同的格式来轻松自定义此代码。您将需要调整此代码片段以根据您的需要对其进行自定义。
更新为了将其作为一个函数,请尝试以下操作:
#!/bin/bash
echo "Enter Directory: ";
read dir
mkdir $dir
moveFiles(){
arg1=$1
counter=0;
while[$counter -ne 3000]; do
mv <source> *.jpg "$dir"
counter++;
if[$counter -e 3000];
then
exit;
fi
done
}
moveFiles "$dir"
exit
同样,此代码可能需要调整。这只是一个例子。
答案4
假设你有一个目录你想要移动的文件出自。
您可以使用:
$ mv <source folder/*.jpg <destination folder/>
编辑:
下面的脚本查找与 定义的搜索条件匹配的所有文件file_screen
,然后执行while
循环以移动选定的文件。
新目录是根据模标准创建的:loop iteration mod files_in_each
.如果 mod 返回零,则会创建新目录并将文件移动到其中。
运行中需要调整的参数:
files_in_each=3000 # controls how many files are placed in each directory
directory_to_move="/home/shadowe/test1/test2" # where are the files located
file_screen="jpg" # only move files that match this criteria
请根据需要进行调整。
#!/bin/bash
# basic definitions and calculations
files_in_each=3000
directory_to_move="/home/shadowe/test1/test2"
file_screen="jpg"
folders_created=0
i=0
# while loop through all of the files that match screening criteria
find $directory_to_move/* -maxdepth 1 -type f -name "*${file_screen}" -print0 | sort -n | while IFS= read -r -d '' file;
do
# modulo control for creating directories every files in each completion
create_dir=`expr $i % $files_in_each`
if [ $create_dir -eq "0" ]
then
new_folder=folder$folders_created
mkdir $new_folder
echo "created new folder: " $new_folder
folders_created=$[$folders_created+1]
fi
mv "$file" $new_folder
i=$[$i+1]
done
小样本运行后结果:
$ ls test2/
not a picture.txt
$ ls folder0/
one.jpg one*two.jpg picture 1.jpg two-one.jpg
one-two.jpg picture 1111.jpg picture *.jpg two three.jpg
大样本结果:
$ ls folder0 | wc -l
3000
$ ls folder1 | wc -l
2008
$ ls test2 | wc -l
7501
$ ls test2/ | grep "jpg"
$
生成测试文件的脚本:
#!/bin/bash
mkdir test2
touch test2/one.jpg
touch test2/'one-two.jpg'
touch test2/'one*two.jpg'
touch test2/'two-one.jpg'
touch test2/'two three.jpg'
touch test2/'picture 1.jpg'
touch test2/'picture *.jpg'
touch test2/'picture 1111.jpg'
touch test2/'not a picture.txt'
#for large test sample uncomment below
#for i in `seq 1 7500`; do touch test2/test$i.txt; done
#for j in `seq 1 5000`; do touch test2/picture$j.jpg; done