我有一个需要排序的271,568个文件的集合,所有这些文件都在同一个目录中。幸运的是,它们都根据它们应该在哪个文件夹中方便地命名。
例如,一小部分文件可能如下所示:
.
├── file.sort.shamwow
├── file.sort.shamwow.abc
├── file.sort.shamwow.example.alsoafile
├── file.sort.shamwow.example.file
├── foo.bar
├── foo.bar.a
├── foo.bar.b
├── foo.lel
├── foo.wow.a.50
└── foo.wow.b
完成排序后,它们应如下所示:
.
├── file
│ └── sort
│ └── shamwow
│ ├── example
│ │ ├── file.sort.shamwow.example.alsoafile
│ │ └── file.sort.shamwow.example.file
│ ├── file.sort.shamwow
│ └── file.sort.shamwow.abc
└── foo
├── bar
│ ├── foo.bar
│ ├── foo.bar.a
│ └── foo.bar.b
├── foo.lel
└── wow
├── foo.wow.a.50
└── foo.wow.b
因此文件foo.wow.a.50
将放在目录wow
内的目录foo
内,对所有文件都是如此。
我想要的程序会根据点到目录的位置对文件进行排序。但是,如果该文件夹中只有一个文件(例如foo/wow/a.50
),则不会仅为该文件创建新文件夹。
现在,我的半功能脚本看起来像:
#!/bin/bash
#organization for gigantic folder
> foo.txt
for f in *; do
d=${f:3}
d=${d%%.*}
d=${d%%.*}
echo $d
if grep -Fxq "$d" foo.txt
then
mkdir -p $d
mv $f $d
else
echo $d >> foo.txt
fi
done
rm foo.txt
但它并没有那么好用。
有人可以修复我的代码,还是自己来解决这个问题?谢谢!
答案 0 :(得分:0)
忽略您的请求输出无法在文件系统上表示(需要相同的名称来引用文件和目录):
#!/bin/bash
# ^^^^- must be bash shebang, must be shell 4.0 or newer
# first pass: count directory references
declare -A refcounts=( )
for f in *; do
f_part=$f
while [[ $f_part = *.* ]]; do
refcounts[$f_part]=$(( ${refcounts[$f_part]} + 1 ))
f_part=${f_part%.*}
done
refcounts[$f_part]=$(( ${refcounts[$f_part]} + 1 ))
done
# second pass: use that information
# ...this is some ugly code, but I don't have the time right now to make it simpler.
for f in *; do
f_part=${f%%.*}
f_rest=${f#*.}
while : "f=$f; f_part=$f_part; f_rest=$f_rest"; do
new_piece=${f_rest%%.*}
[[ $new_piece ]] || break
f_part_next=${f_part}.$new_piece
f_rest_next=${f_rest#"$new_piece"}; f_rest_next=${f_rest_next#.}
if [[ $f_rest = *.* ]] && (( ${refcounts[${f_part_next}]:-0} > 1 )); then
f_part=$f_part_next
f_rest=$f_rest_next
else
break
fi
done
dest="${f_part//"."/"/"}/${f_rest}"
mkdir -p -- "${dest%/*}"
mv -- "$f" "$dest"
done