查找具有匹配子字符串的文件并将它们移动到目录中

查找具有匹配子字符串的文件并将它们移动到目录中

我的目录包含以或.idat结尾的文件对列表。_Grn_Red

对于每一对,我想创建一个以第一个_分隔符之前的子字符串命名的目录,并将文件移动到各自的目录中。

如果目录不存在,请在移动文件之前创建它们。

我的代码:

for file in *.idat; 
do directory_name=${file%_*} \ 
mkdir directory_name \ 
if ${file%_*}==directory_name; 
then 
mv $file directory_name;
fi; 
done

追溯:

-bash: syntax error near unexpected token `then'

文件名:

00f3408c-5ad1-4afb-9eac-3392aa92e42c_noid_Grn.idat 
00f3408c-5ad1-4afb-9eac-3392aa92e42c_noid_Red.idat 

0317b249-9256-47fe-9533-3ca91c07e3fd_noid_Grn.idat 
0317b249-9256-47fe-9533-3ca91c07e3fd_noid_Red.idat

039f8688-b4cd-4931-a8f5-40bcb1fbd8f0_noid_Grn.idat  
039f8688-b4cd-4931-a8f5-40bcb1fbd8f0_noid_Red.idat

预期的文件夹名称:

00f3408c-5ad1-4afb-9eac-3392aa92e42c
0317b249-9256-47fe-9533-3ca91c07e3fd
039f8688-b4cd-4931-a8f5-40bcb1fbd8f0

答案1

应该是这样的:

shopt -s nullglob extglob # dotglob
for file in [^_]*_@(Grn|Red).idat; do
  dirname=${file%%_*}
  mkdir -p -- "$dirname" &&
    mv -- "$file" "$dirname"
done

dotglob(如果您还想考虑隐藏的,请取消注释)。

\该行的末尾是一个行延续。它用于打破长行以提高可读性。

do directory_name=${file%_*} \ 
mkdir directory_name \ 
if ${file%_*}==directory_name

是相同的

do directory_name=${file%_*} mkdir directory_name if ${file%_*}==directory_name

因此它会要求mkdir创建名为directory_name,的目录if00f3408c-5ad1-4afb-9eac-3392aa92e42c_noid==directory_namedirectory_name=00f3408c-5ad1-4afb-9eac-3392aa92e42c_noid在其环境中传递。

然后 shell 会抱怨then没有相应的if.

要在 中进行模式匹配bash,您可以使用case构造函数或[[ text = pattern ]]运算符,但这里不需要。

--另请记住,列表上下文中的扩展必须在 bash 中引用,并且对于大多数命令,非选项参数必须与选项分开。

${var%pattern}删除最短与 末尾的模式匹配的字符串$var。您需要${var%%pattern}删除最长的字符串才能删除第一个字符串中的所有字符串_。您会注意到,我们使用[^_]*... as glob 模式来确保文件不以 a 开头,_这会导致空目录名。

Grn如果您知道每个文件总是有一个文件,则可以通过执行以下操作将和 的Red调用次数减少一半:mkdirmv

shopt -s nullglob # dotglob
for file in [^_]*_Red.idat; do
  dirname=${file%%_*}
  mkdir -p -- "$dirname" &&
    mv -- "$file" "${file%_*}_Grn.idat" "$dirname"
done

相关内容