我尝试通过脚本组织我的文件和文件夹。它使用我的文件的第一个字母创建文件夹并将其移动到那里。
第一次,脚本完成这项工作,但如果我创建新文件并再次执行脚本,它会在文件夹中创建一个新的子文件夹,依此类推。
例如,它创建T/T/toto.txt
.
我的脚本:
for first in $(ls -1 | sed 's/^\(.\).*$/\1/' | tr '[a-z0-9]' '[A-Z0-9]' | uniq)
do
mkdir tmp
mv "$first"* tmp/
lower=$(echo $first | tr '[A-Z]' '[a-z]')
mv "$lower"* tmp/
mv tmp/ "$first";
done
答案1
你的脚本正在执行中目录和非目录文件,并根据它们的名称将它们移动到子目录中,即使它们是我们要排序的单字母目录。这就是新目录的显示方式。您的代码还不必要地使用sed
等tr
来执行bash
shell 可以更快更安全地执行的操作。此外,ls
决不应该在脚本中使用它来迭代文件名(参见,例如为什么*不*解析`ls`(以及该怎么做)?为什么)。
另一个问题是,如果您有数千个名称以相同字符开头的文件,则该mv "$first"* tmp/
命令(或第二个mv
)可能会失败,并出现“参数列表太长”错误(请参阅例如参数列表对于 ls 来说太长;该问题适用于mv
所有其他外部命令,而不仅仅是ls
)。
解决这些问题的示例脚本仅使用bash
except from 和mkdir
中的功能mv
:
#!/bin/bash
shopt -s nullglob # makes the loop not loop at all if there are no files
for name in *; do
if [[ -d $name ]] && [[ $name == ? ]]; then
# skip directories that have single character names
continue
fi
# get first character in filename
first=${name:0:1}
# compute destination directory name from this first
# character by uppercasing it
destdir=${first^}
# make that directory if it does not already exist
mkdir -p -- "$destdir"
# move the file into place (name collisions not checked for)
mv -- "$name" "$destdir"
done
--
调用中的选项并mkdir
防止mv
可能以破折号开头的文件名(请参见,例如“--”(双破折号)是什么意思?)。
该脚本的主要区别在于,我循环遍历目录中的名称,而不是像您一样遍历第一个字符。