bash逐行更改文件中的绝对路径以创建脚本
我正在尝试基于输入文件(list.txt)创建一个bash脚本。输入文件包含具有绝对路径的文件列表。输出应该是一个bash脚本(move.sh),它将文件移动到另一个位置,保留文件夹结构,但在之前稍微更改目标文件夹名称 Input list.txt文件示例如下所示:bash逐行更改文件中的绝对路径以创建脚本,bash,sed,directory,move,absolute-path,Bash,Sed,Directory,Move,Absolute Path,我正在尝试基于输入文件(list.txt)创建一个bash脚本。输入文件包含具有绝对路径的文件列表。输出应该是一个bash脚本(move.sh),它将文件移动到另一个位置,保留文件夹结构,但在之前稍微更改目标文件夹名称 Input list.txt文件示例如下所示: /In/Folder_1/SomeFoldername1/somefilename_x.mp3 /In/Folder_2/SomeFoldername2/somefilename_y.mp3 /In/Folder_3/SomeFol
/In/Folder_1/SomeFoldername1/somefilename_x.mp3
/In/Folder_2/SomeFoldername2/somefilename_y.mp3
/In/Folder_3/SomeFoldername3/somefilename_z.mp3
/gain/Folder_1/somefilename_x.mp3
/gain/Folder_2/somefilename_y.mp3
/gain/Folder_3/somefilename_z.mp3
创建后,输出文件(move.sh)应如下所示:
mv "/In/Folder_1/SomeFoldername1/somefilename_x.mp3" /gain/Folder_1/
mv "/In/Folder_2/SomeFoldername2/somefilename_y.mp3" /gain/Folder_2/
mv "/In/Folder_3/SomeFoldername3/somefilename_z.mp3" /gain/Folder_3/
应该或多或少地保留文件夹结构
执行创建的bash脚本(move.sh)后,结果如下所示:
/In/Folder_1/SomeFoldername1/somefilename_x.mp3
/In/Folder_2/SomeFoldername2/somefilename_y.mp3
/In/Folder_3/SomeFoldername3/somefilename_z.mp3
/gain/Folder_1/somefilename_x.mp3
/gain/Folder_2/somefilename_y.mp3
/gain/Folder_3/somefilename_z.mp3
我到目前为止所做的一切
1.创建具有绝对路径的文件列表
2.创建move.sh脚本
rsync不是一个选项,因为我需要完全控制要移动的文件
我能做些什么更好地解决这个问题
EDIT:@Socowi为我指明了正确的方向,帮了我很多忙。在我深入研究正则表达式之后,我可以解决我的问题。非常感谢它不是bash内置的,但是
mmv
命令非常适合这种需要在路径中使用通配符的mv
。类似于以下的方法应该可以工作:
mmv "in/*/*/*" "#1/#3"
请注意,这不会为您创建目录-但在上面的示例中,这些目录似乎已经存在
该脚本只使用${fields[1]}的值,即文件夹_1,并将其放在末尾的所有行中。而不是文件夹2和文件夹3
迭代所有行,并为每行更新字段。完成循环后,字段
保留其值(从最后一行开始)。您必须将sed
命令移动到循环中,并确保只有当前行被sed
替换。然而,有一个更好的方法——见下文
我还能做得更好吗
例如,有很多事情你可以改进
- 使用
mapfile-d/fields
而不是printf
+cut
+($())
创建数组字段
。这样,路径中的空间也不会有问题
- 仅使用
sed
一次,而不是创建数组字段
并使用多个sed
命令。您可以使用以下小脚本替换步骤2:
但是,最好的优化方法是放弃这三步方法,只使用一个脚本来查找和移动文件:
find /In/ -iname "*.mp3" -type f -exec rename -n 's|^/.*?/(.*?)/.*/(.*)$|/gain/$1/$2|' {} +
-n
选项将打印要重命名的内容,而不实际重命名任何内容。如果对结果满意,请删除-n
。以下是输出:
rename(/In/Folder_1/SomeFoldername1/somefilename_x.mp3, /gain/Folder_1/somefilename_x.mp3)
rename(/In/Folder_2/SomeFoldername2/somefilename_y.mp3, /gain/Folder_2/somefilename_y.mp3)
rename(/In/Folder_3/SomeFoldername3/somefilename_z.mp3, /gain/Folder_3/somefilename_z.mp3)
您编写了done
。你是说done
?done
只是第1行定义的done
的副本。我保持完成
用于其他活动。啊,我明白了。另一个问题;您想只移动mp3文件还是移动完整目录?如果您只想移动mp3文件:目标目录是否已经存在或是否应该创建?仅移动mp3。目标目录/gain/Folder\u x/
已存在。但目录/gain/Folder\u 1/SomeFoldername1
不存在。好的。我试图应用sed-iE的^/[^/]*/([^/]*).$|mv“&”/gain/\1“|”/home/maars/mp3/move.sh
但是得到了一个错误:sed:-e表达式1,char 40:s命令的RHS上的无效引用\1
sed
似乎不允许速记形式-iE
。用-i-E
再试一次。请参阅编辑。它使用了-i-E
我需要使用find/In/-iname“*.mp3”-type f-exec rename-n's |^/*?/(.*)/(.*)/(.*)$|/gain/$1/$2 |{}+
来理解它。因为它还没有给我任何输出。也许你有一个不同的rename
比我想象的。在Ubuntu上,重命名是指向/usr/bin/file rename
的符号链接。该程序由Larry Wall编写(请参见man rename | grep-A1 AUTHOR
)和rename--version
使用File::rename version 0.20打印/usr/bin/rename。在其他系统上,相同的命令可能有不同的名称,例如prename
。有关更多信息,请参阅和。我需要先安装重命名
。
find /In/ -iname "*.mp3" -type f -exec rename -n 's|^/.*?/(.*?)/.*/(.*)$|/gain/$1/$2|' {} +
rename(/In/Folder_1/SomeFoldername1/somefilename_x.mp3, /gain/Folder_1/somefilename_x.mp3)
rename(/In/Folder_2/SomeFoldername2/somefilename_y.mp3, /gain/Folder_2/somefilename_y.mp3)
rename(/In/Folder_3/SomeFoldername3/somefilename_z.mp3, /gain/Folder_3/somefilename_z.mp3)