需要压平目录,修改文件名。用bash?

时间:2011-03-31 01:34:32

标签: linux bash directory

我有一个包含50,000多个文件的目录结构。文件名的格式为<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
...

我希望平面文件列表的格式为

<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&amp;正则表达式,并希望了解如何实现这一点。

我知道如何生成路径列表,但不知道如何应用正则表达式来转换表单。我会使用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命令上使用find,但无法弄清楚如何让awk使用\0作为记录终结符({{ 1}}不起作用)。我认为问题与换行有关,但我不知所措!

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

我必须调整接受的答案才能为我工作:

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)
}'

答案 2 :(得分:1)

sed出现时,通常无需使用awk。这是另一个不分叉额外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) }'

编辑,您可以在cp

内进行awk
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)
}'

答案 3 :(得分:-1)

要复制文件:

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