我的一个目录中有 5000 个文件和 50 个子目录。我想将每 100 个文件移动到每个目录。有人能提供一些建议吗?提前谢谢。
file_count=$(ls ABC* | wc -l)
echo $file_count
i=1
dir_count=$(( file_count / 100))
echo $dir_count
dir_count1=`expr $dir_count + 1 `
while [ $i -lt $dir_count1 ]
do
mkdir $i
i=`expr $i + 1`
done
这就是我创建目录运行时并希望将脚本第一行返回的文件复制到每个目录的方式。每个目录应该有 100 个文件。
答案1
可能有更优雅的方法来实现这一点。但是这个方法有效
files_per_dir=100
file_count=$(ls -1 ABC* | wc -l)
dir_count=$((file_count / files_per_dir))
echo $dir_count
dir_count1=$(expr $dir_count + 1)
echo $dir_count1
for idir in $(seq 1 ${dir_count1}) ; do
file_list=$(find . -maxdepth 1 -type f | grep -v au_ | head -${files_per_dir} | tr '\r\n' ' ')
echo $file_list
mkdir $idir
mv $file_list $idir
done
笔记:
- 我
grep -v au_
在管道中使用以避免我的 bash 脚本(名为au_...
)被移动。您可能需要不同的字符串,或者根本不需要它。 - 该
seq
循环取代了你的while
循环。 ls -1 ABC* | wc -l
可以替换为ls ABC* | wc -w
。
答案2
除非您需要以某种“循环”方式将文件分发到各个新目录中,否则我建议根据需要创建目标目录,如下所示:
#!/bin/bash
shopt -s nullglob
nPer=100
files=( ABC* )
i=0;
while (( i < ${#files[@]} )); do
if ! (( i % nPer )); then
newDir=dir$(( 1 + i/nPer ))
echo mkdir -p "$newDir" || break
fi
echo mv -nt "$newDir" -- "${files[i]}"
((++i))
done
或 POSIXly
#!/bin/sh
nPer=100
set -- ABC*
i=0;
while [ $# -gt 0 ] && [ -e "$1" ]; do
if [ $((i % nPer)) -eq 0 ]; then
newDir=dir$((1 + i/nPer))
echo mkdir -p "$newDir" || break
fi
echo mv -nt "$newDir" -- "$1"
shift
i=$((i + 1))
done
echo
一旦您确认它做了正确的事情,就可以删除s。
使用 nPer=10 和一个包含 42 个 ABC* 文件的目录进行测试(不是 nPer 的倍数,这样我们才能看到边缘发生的情况):
$ ls ABC*
ABC01 ABC04 ABC07 ABC10 ABC13 ABC16 ABC19 ABC22 ABC25 ABC28 ABC31 ABC34 ABC37 ABC40
ABC02 ABC05 ABC08 ABC11 ABC14 ABC17 ABC20 ABC23 ABC26 ABC29 ABC32 ABC35 ABC38 ABC41
ABC03 ABC06 ABC09 ABC12 ABC15 ABC18 ABC21 ABC24 ABC27 ABC30 ABC33 ABC36 ABC39 ABC42
$ ./myscript
$ ls
dir1 dir2 dir3 dir4 dir5 myscript
$
$ ls dir?
dir1:
ABC01 ABC02 ABC03 ABC04 ABC05 ABC06 ABC07 ABC08 ABC09 ABC10
dir2:
ABC11 ABC12 ABC13 ABC14 ABC15 ABC16 ABC17 ABC18 ABC19 ABC20
dir3:
ABC21 ABC22 ABC23 ABC24 ABC25 ABC26 ABC27 ABC28 ABC29 ABC30
dir4:
ABC31 ABC32 ABC33 ABC34 ABC35 ABC36 ABC37 ABC38 ABC39 ABC40
dir5:
ABC41 ABC42