所有文件都在一个目录中(超过500 000个文件),以下列模式命名
AR00001_1
AR00001_2
AR00001_3
AR00002_1
AR00002_2
AR00002_3
我需要一个脚本,可以是批处理或unix shell,它可以将AR00001的所有内容移动到一个名为AR00001的新文件夹中,并对AR00002文件执行相同的操作等。
这是我到目前为止一直想弄清楚的事情
for f in *_*; do
DIR="$( echo ${f%.*} | tr '_' '/')"
mkdir -p "./$DIR"
mv "$f" "$DIR"
done
由于
//更新
在CMD中使用
for %F in (c:\test\*) do (md "d:\destination\%~nF"&move "%F" "d:\destination\%~nF\") >nul
似乎几乎是我想要的,除了它不会将前7个字符作为子字符串,而是为每个文件创建一个文件夹:/我试图将它与您的解决方案混合
答案 0 :(得分:3)
@echo off
setlocal enabledelayedexpansion
for %%a in (???????_*) do (
set "x=%%a"
set "x=!x:~0,7!"
md "!x!" >nul
move "!x!*" "!x!\" 2>nul
)
每个匹配文件的执行:
- 获得前7个字符
- 创建具有该名称的文件夹(忽略错误消息,如果存在)
- 移动所有以这7个字符开头的文件(忽略错误消息,如果文件不存在(已移动))
答案 1 :(得分:2)
以下方法可实现所需效果,并在每次创建目标目录之前检查目标目录是否存在。
@echo off
setlocal ENABLEDELAYEDEXPANSION
set "TOBASE=c:\target\"
set "MATCHFILESPEC=AR*"
for %%F in ("%MATCHFILESPEC%") do (
set "FILENAME=%%~nF"
set "TOFOLDER=%TOBASE%!FILENAME:~0,7!"
if not exist "!TOFOLDER!\" md "!TOFOLDER!"
move "%%F" "!TOFOLDER!" >nul
)
endlocal
在move
命令中,通过仅移动当前文件而不是包含通配符,我们确保我们不会占用下一次可能在循环中出现的文件名。保持简单,假设效率不是最重要的。
我建议通过创建批处理文件(使用.bat
或.cmd
扩展名)来进行原型设计,而不是尝试在单行上交互式地执行复杂任务。行为可能不同,您可以在批处理文件中执行更多操作,例如使用setlocal
打开变量的延迟扩展。它也只是用交互式%F
使用%%F
进行循环的痛苦写作,只需记住在粘贴到批处理时将所有这些转换为%%~nF
,dir /x /p AR*
等为后代提供文件。
提醒一句:文件夹中包含500,000个文件,并且所有文件都具有非常相似的前缀,如果您的文件系统启用了8.3目录命名(通常是默认设置),则可能会遇到问题通配符。这种情况发生在8.3命名空间变得越来越忙,并且文件名以8个字符编码的方式越来越少。 (哈希表填满并开始溢出到意外的文件名中。)
一种解决方案是在服务器上关闭该功能,但这可能会对任何遗留应用程序产生严重影响。要查看8.3命名方案中文件的样子,您可以这样做,例如:
ARB900~1.TST AR15467_RW322.tst
AR85E3~1.TST AR15468_RW322.tst
ARDDFE~1.TST AR15469_RW322.tst
AR1547~1.TST AR15470_RW322.tst
AR1547~2.TST AR15471_RW322.tst
...
...这可能会给你类似的东西(左手的名字是转换为8.3的那个):
for %a in (AR8*) do @echo %a
在这个例子中,由于似乎维护了前两个字符,因此不应该发生冲突。
因此,例如,如果我说AR15468_RW322.tst
AR18565_RW322.tst
AR20376_RW322.tst
AR14569_RW322.tst
AR17278_RW322.tst
...
,我会得到最初看起来可能不正确的内容:
AR8*
但这实际上是正确的;它是长文件名和短文件名格式中匹配???????_*
的所有文件。
编辑:回想起来,我很清楚这个解决方案与Stephan的解决方案非常相似,在我自己开始工作之前,我已经浏览了现有的答案,所以我应该相信他。我将通过指出Stephan的解决方案的好处来尝试挽回面子。它使用通配符应该绕过任何8.3命名问题:通过将通配符指定为AR?????_*
,它只捕获长文件名并且不会匹配任何转换后的8.3文件名(所有这些名称都没有在那个位置下划线)。同样,$("#sub").click(function() {
之类的通配符也会这样做。
答案 2 :(得分:1)
使用bash,你可以写:
for f in *; do
[[ -d $f ]] && continue # skip existing directories
prefix=${f:0:7} # substring of first 7 characters
mkdir -p "$prefix" # create the directory if it does not exist
mv "$f" "$prefix" # and move the file
done
对于子字符串扩展,请参阅https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion - 这可能是您错过的一点。