将目录中的所有文件小写,期望在某个时候撤消它

将目录中的所有文件小写,期望在某个时候撤消它

好的,我想批量重命名目录中的文件(以及子目录中的文件)为小写,但我还想在某个时候撤消该操作。我是否应该将它们的真实名称存储在某个地方,以便完成后可以返回原始结构?

这可以在 bash 中完成吗?

答案1

是的,很简单

for f in *; do
    mv "$f" "${f,,}"
    printf "mv %q %q\n" "${f,,}" "$f" >> restore.sh
done

运行bash restore.sh以恢复以前的文件名。


递归:比第一次出现时更棘手:我最终分别处理了文件和目录,只重命名了路径的基本部分。

declare -A restore=([f]=restore_file.sh [d]=restore_dir.sh)
for type in f d; do
    find . -type $type -print0 | while IFS= read -rd '' path; do
        base=$(basename "$path")
        lower="$(dirname "$path")/${base,,}"
        mv "$path" "$lower"
        printf "mv %q %q\n" "$lower" "$path" >> "${restore[$type]}"
    done
done

恢复:

bash restore_dir.sh
bash restore_file.sh

答案2

重命名非常简单,只需使用 进行一点变换即可rename。以下是无效的(删除 -n 标志以使其执行操作),它会告诉您它在做什么:

rename 'tr/A-Z/a-z/' -vn * 

但是,如果您想将其构建成可逆脚本,您还需要做更多的事情:

rename 'tr/A-Z/a-z/' -vn * | sed 's/ renamed as /#/' | awk -F'#' '{print "mv '\''" $2 "'\'' '\''" $1 "'\''"}' > reverse.sh

如果您需要更改进入此列表的文件(例如递归),您可以通过管道将名称重命名:

find | rename ...

或者使用一些 Bash 选项进行递归遍历:

shopt -s globstar
rename ... ** *

答案3

#!/bin/bash

IFS=$'\n'
WORKING_PATH=$(pwd $1)

RESTORE_FILENAME="$WORKING_PATH/restore_case.sh"

echo "#!/bin/bash" > "$RESTORE_FILENAME"
chmod a+x "$RESTORE_FILENAME"


for FILEPATH in $(find . -type f)
do
    FILENAME="${FILEPATH##*/}"
    LOWER_FILE="${FILEPATH::-${#FILENAME}}${FILENAME,,}"

    if [ "$LOWER_FILE" != "$FILEPATH" ]; then
        echo moving "$FILEPATH" to "$LOWER_FILE"
        echo mv \""$LOWER_FILE"\" \""$FILEPATH"\" >> "$RESTORE_FILENAME"_files
        mv "$FILEPATH" "$LOWER_FILE"
    fi
done

touch "$RESTORE_FILENAME"_dirs

for DIRPATH in $(find . -type d -printf "%d%p\n"|sort -nr)
do
    DIRPATH=${DIRPATH:1}
    DIRNAME="${DIRPATH##*/}"
    LOWER_DIRPATH="${DIRPATH::-${#DIRNAME}}${DIRNAME,,}"
    if [ "$LOWER_DIRPATH" != "$DIRPATH" ]; then
        echo moving "$DIRPATH" to "$LOWER_DIRPATH"
        echo -e "mv \""$LOWER_DIRPATH"\" \""$DIRPATH"\"\n$(cat "$RESTORE_FILENAME"_dirs)" > "$RESTORE_FILENAME"_dirs
        mv "$DIRPATH" "$LOWER_DIRPATH"
    fi
done

cat "$RESTORE_FILENAME"_dirs "$RESTORE_FILENAME"_files >> "$RESTORE_FILENAME"
rm "$RESTORE_FILENAME"_dirs "$RESTORE_FILENAME"_files

echo rm '$0' >> "$RESTORE_FILENAME"

更长,有点脏,但更精确,也不会做不必要的mv

相关内容