Unix下如何利用参数化变量实现多文件一次性批量移动?
问题描述
已将目标文件名(无路径)存入逗号分隔的变量:var="M1.txt,A2.dat,T300.log"
直接使用花括号展开的命令可正常完成移动:mv /home/rrajendr/test1/{M1.txt,A2.dat,T300.log} /home/rrajendr/test2/
但尝试参数化调用时失败:mv /home/rrajendr/test1/{"$var"} /home/rrajendr/test2/
错误信息
mv: cannot stat ‘/home/rrajendr/test1/{M1.txt,A2.dat,T300.log}: No such file or directory
系统将{M1.txt,A2.dat,T300.log}识别为单个文件名,未触发花括号的多文件拆分。以下尝试均无效:
mv /home/rrajendr/test1/echo $var-t /home/rrajendr/test2/mv /home/rrajendr/test1/{$var}mv /home/rrajendr/test1/{echo $var}
需求约束
- 源路径固定,避免为每个文件重复拼接完整路径;
- 不切换工作目录,需同时执行aws cli、snow cli等其他操作;
- 文件名已以逗号分隔形式存入变量;
- 不使用Python等外部程序,不采用shell循环或xargs;
- 单条命令完成批量移动。
有效解决方法
方法1:使用eval强制重新解析命令
这是最贴合原有花括号展开习惯的方案,利用eval让bash重新执行命令行展开流程:
eval mv /home/rrajendr/test1/{$var} /home/rrajendr/test2/
执行时,$var先展开为M1.txt,A2.dat,T300.log,得到mv /home/rrajendr/test1/{M1.txt,A2.dat,T300.log} /home/rrajendr/test2/,随后bash会触发花括号展开,将其拆分为多个文件路径参数,最终完成批量移动。
方法2:字符串替换生成完整路径列表
通过bash的字符串替换,直接拼接所有文件的完整路径:
mv $(echo "/home/rrajendr/test1/${var//,/ /home/rrajendr/test1/}") /home/rrajendr/test2/
原理:${var//,/ /home/rrajendr/test1/}将变量中的每个逗号替换为 /home/rrajendr/test1/,最终生成/home/rrajendr/test1/M1.txt /home/rrajendr/test1/A2.dat /home/rrajendr/test1/T300.log的路径列表,作为mv的参数。
方法3:数组前缀拼接(bash专属)
利用bash数组将文件名拆分,再统一添加源路径前缀:
IFS=, read -ra files <<< "$var"; mv "${files[@]/#/\/home\/rrajendr\/test1\/}" /home/rrajendr/test2/
IFS=, read -ra files将逗号分隔的变量转为数组,${files[@]/#/\/home\/rrajendr\/test1\/}为数组中每个元素添加源路径前缀,最终传递给mv命令完成批量移动。
内容的提问来源于stack exchange,提问作者Rajbharath

