需要拼合一个目录,修改文件名。 用bash?

我有一个目录结构有超过50,000个文件。 文件名的forms是<YYMMDD>-<NNN>.htm

目录结构是

/<category>/<YYYY>/<MM>/

例如:

 ./Racing/1998/03/980320-001.htm ./Racing/1998/03/980320-002.htm ... ./General/1999/02/990221-001.htm ./General/1999/02/990221-002.htm ... 

我想要的文件的平面列表的forms

<category>-<YYYY>-<MM>-<DD>-<NNN>

所以上面是

 Racing-1998-03-20-001.htm Racing-1998-03-20-002.htm ... General-1999-02-21-001.htm General-1999-02-21-002.htm 

我(重新)学习bash和正则expression式,并会欣赏一些关于如何实现这一点的指针。

我知道如何生成path列表,但不知道如何应用正则expression式来转换表单。 我会使用find -type f -name "*.htm" | <some goblygook here> find -type f -name "*.htm" | <some goblygook here>

这里<some goblygook here>可能会利用xargs

提前致谢。

[编辑3/30 9:58 pm]

根据下面的答案,我编造了这个脚本。 我不能让xargs工作:

 #!/bin/bash mkdir ./flat find -type f -name "*.htm" | \ awk -F'[/]' ' BEGIN{OFS="-"} { gsub(/^\.\//,"") ;print "./" $0 " ./flat/" $1,$2, substr($4,3,2),substr($4,5,2),substr($4,8)} ' | \ xargs -p -d "\n" -n 1 cp 

运行这个给我:

 $ ./awktest.sh mkdir: cannot create directory `./flat': File exists cp ./General/1997/05/970525-002.htm ./flat/General-1997-05-25-002.htm ?...y cp: missing destination file operand after `./General/1997/05/970525-002.htm ./flat/General-1997-05-25-002.htm' Try `cp --help' for more information. ^C 

从该输出复制确切的cp命令( cp ./General/1997/05/970525-002.htm ./flat/General-1997-05-25-002.htm ),并直接粘贴到bash提示符中。

我试图找出如何在-print0命令上使用-print0 ,但无法弄清楚如何让awk使用\0作为logging终止符( RS="\0"不起作用)。 我认为这个问题与换行有关,但是我不知所措。

awk存在时通常不需要使用sed 。 这是另一个答案,不fork额外的sed进程

 find -type f -name "*.htm" | awk -F'[/]' 'BEGIN{OFS="-"}{ gsub(/^\.\//,"") ;print $1,$2, substr($4,3,2),substr($4,5,2),substr($4,8) }' 

编辑,你可以在awk做你的cp

 find -type f -name "*.htm" | awk -F'[/]' 'BEGIN{OFS="-"}{ gsub(/^\.\//,"") source = $1 OFS $2 OFS substr($4,3,2) OFS substr($4,5,2) OFS substr($4,8) destination = <create your destination here> command = "cp "source" "destination system(command) }' 

find -type f -name "*.htm" | sed 's@^./@@g;s@/@-@g' | awk -F'-' '{print $1 "-" $2 "-" $3 "-" substr($4, 5, 2) "-" $5}'

sed & awk对文本操作非常有用。

我不得不调整接受的答案为我工作:

 find -type f -name "*.png" | awk -F'[/]' 'BEGIN{OFS="_"}{ gsub(/^\.\//,"") source = "source root folder" $1 "/" $2 "/" $3 destination = "destination folder" $1 OFS $2 OFS $3 command = "cp "source" "destination system(command) }' 

要像这样复制文件:

 eval "`find -type f -name "*.htm" |awk -F/ '{print "cp " $0 " " $2 "-" $3 "-" $4 "-" substr($5,5) ";" }'`"