我有一个旧的 .bat 文件,需要在我的 QNAP 上运行。我需要为每个文件递归创建文件夹(基于文件名),然后将文件移动到该文件夹。
这是旧的.bat:
@echo off
for %%a in (*.*) do (md "%%~na" 2>nul
move "%%a" "%%~na"
)
如果我正确理解 .bat 语法,这应该基本上是等效的:
#!/bin/sh
for a in *
do
[ ! -f "$a" ] && continue # skip anything that is not a regular file
dirname="${a%.*}" # trim off the last suffix
mkdir -p "$dirname" && mv -i "$a" "$dirname/"
done
与原始脚本一样,此脚本将仅处理当前目录中的文件。如果您需要处理当前目录及其所有预先存在的子目录(这就是我对“递归”的理解)它会变得更加复杂,因为脚本必须以深度优先的方式进行以避免尝试将文件推送到无限深的 sub-sub-sub... 目录中。
在这种情况下,需要开发不同的解决方案,很可能使用find
命令来收集文件名。该find
命令默认是递归的:它将自动处理指定目录及其所有子目录,除非您明确告诉它不要这样做。所以这是一个递归版本,可以处理任意目录中任意数量的文件:
#!/bin/sh
# FIXME: needs more protection against unusual filename characters
find . -type f -depth | while read a
do
dirname="${a%.*}" # trim off the last suffix
mkdir -p "$dirname" && mv -i "$a" "$dirname/"
done
但是,它有一个小问题:如果文件名包含换行符,它可能无法正确处理该文件名。但是,如果您的文件的名称中只有表现良好的字符,那么这就足够了。