Bash 脚本将文件排序到按字母顺序排列的文件夹中

Bash 脚本将文件排序到按字母顺序排列的文件夹中

我尝试通过脚本组织我的文件和文件夹。它使用我的文件的第一个字母创建文件夹并将其移动到那里。

第一次,脚本完成这项工作,但如果我创建新文件并再次执行脚本,它会在文件夹中创建一个新的子文件夹,依此类推。

例如,它创建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

你的脚本正在执行中目录和非目录文件,并根据它们的名称将它们移动到子目录中,即使它们是我们要排序的单字母目录。这就是新目录的显示方式。您的代码还不必要地使用sedtr来执行bashshell 可以更快更安全地执行的操作。此外,ls决不应该在脚本中使用它来迭代文件名(参见,例如为什么*不*解析`ls`(以及该怎么做)?为什么)。

另一个问题是,如果您有数千个名称以相同字符开头的文件,则该mv "$first"* tmp/命令(或第二个mv)可能会失败,并出现“参数列表太长”错误(请参阅例如参数列表对于 ls 来说太长;该问题适用于mv所有其他外部命令,而不仅仅是ls)。

解决这些问题的示例脚本仅使用bashexcept 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可能以破折号开头的文件名(请参见,例如“--”(双破折号)是什么意思?)。

该脚本的主要区别在于,我循环遍历目录中的名称,而不是像您一样遍历第一个字符。

相关内容