`使用regex模式查找-name`并使用`cp替换文件名`

`使用regex模式查找-name`并使用`cp替换文件名`,regex,file,shell,cron,find,Regex,File,Shell,Cron,Find,目前,我正在使用cron中的命令将*。数据从源路径复制到目标路径: find /source_path -name *.data -exec cp {} /target_path \; 源结构是: /source_path/category1/001.data /source_path/category1/002.data /source_path/category2/003.data /source_path/category3/004.data /s

目前,我正在使用
cron
中的命令将
*。数据从源路径复制到目标路径:

find /source_path -name *.data -exec cp {} /target_path \;
源结构是:

    /source_path/category1/001.data
    /source_path/category1/002.data
    /source_path/category2/003.data
    /source_path/category3/004.data
    /source_path/categorya/005.data
    /source_path/categoryb/006.data
执行上述
cron
命令后,目标将包含:

    /target_path/001.data
    /target_path/002.data
    /target_path/003.data
    /target_path/004.data
    /target_path/005.data
    /target_path/006.data
    /target_path/category1_001.data
    /target_path/category1_002.data
    /target_path/category2_003.data
    /target_path/category3_004.data
    /target_path/categorya_005.data
    /target_path/categoryb_006.data
我需要一个单行解决方案来替换当前的cron命令,以便在执行后,目标将包含:

    /target_path/001.data
    /target_path/002.data
    /target_path/003.data
    /target_path/004.data
    /target_path/005.data
    /target_path/006.data
    /target_path/category1_001.data
    /target_path/category1_002.data
    /target_path/category2_003.data
    /target_path/category3_004.data
    /target_path/categorya_005.data
    /target_path/categoryb_006.data
附加子目录名作为目标文件名的前缀


谢谢。

检查此仅打印字符串的命令:

$ find /source_path -name \*.data  | while read -r filename; do printf "print version: cp %s %s\n" "${filename}" "$(printf "%s\n" "${filename}" | sed "s/^.*[/]\(category[^/]*\)[/]\(.*[.]data\)$/\/target_path\/\1_\2/")"; done
find命令打印找到的文件名,每行一个

读取-r文件名读取一行文本并将其存储到文件名变量中

查找…|在一起读取-r filename时,将文件名列表写入管道中,每行一个。一次只能读取一个文件名。对于每次读取的文件名,将在执行时将命令插入

sed
命令将路径名/source\u path/category1/001.data更改为/target\u path/category1\u 001.data

我尽力在下面几行中解释sed的字符串参数,但是如果您要询问这些主题,您应该阅读:

s/是搜索和替换sed命令,后跟3个元素:“s/regex pattern/replacement/flag”

^在最开始处表示行的开始

表示任何一个字符

*表示前面指定的字符数为0或无限

[/]表示一个字符,字符/。[]用于转义/,否则它将被解释为正则表达式模式替换标志之间的分隔符

合计^.*[/],表示以任何零个或多个字符开头的行。此启动顺序必须以/结束

[^/]表示一个字符,^开头表示不属于所列字符的一部分。因此,它表示除/之外的任何一个字符

[abc]介于[]之间,表示一个字符:a或b或c

正则表达式模式中遇到的第一个\(.*)可以在替换中用\1引用。在正则表达式模式中遇到的第二个\(.*)可以在替换中用\2引用。等。如果没有转义字符,表示单个字符
),则无法引用内容

完成后,使用cp来有效复制文件:

find /source_path -name \*.data  | while read -r filename; do cp "${filename}" "$(printf "%s\n" "${filename}" | sed "s/^.*[/]\(category[^/]*\)[/]\(.*[.]data\)$/\/target_path\/\1_\2/")"; done

sed-r-e的/\/source(\u path)\/(category.+)\/([0-9]+\.data)/\/target\1\/\2\u3/gm'source\u file>target\u file
这段代码做什么?我不熟悉sed,但它看起来像是替换。它是否遍历源路径并从源复制到目标?此外,
category
可以是任何东西,包含破折号、下划线等,而不仅仅是以单词category开头。谢谢你说得对。这是替换。我假设这些路径在一个文件中,并将其更改并保存在另一个文件中。你想要这个还是别的什么?我想你正在尝试复制文件并重命名它。是吗?实际上,这些是文件系统中的实际文件和路径。这就是为什么需要使用
cp
命令的原因。我需要保持原始源不受影响,同时将每个.data文件复制到目标路径,并将category_name附加为文件名前缀。我正在考虑是否可以将匹配的category存储到一个变量中,然后将其与
cp
命令一起使用?这个解决方案在打印字符串的测试运行中对我有效。我还没有已执行实际运行。我将
(类别[^/]*\)
替换为
(.*[^/]*\)
匹配任何可能的字符,因为类别实际上是不同的名称。你能给我一些快速的解释吗?我读不懂。当read-r filename
时,
做了什么,并与
进行交互,查找
sed
?还有
[/]
[^/]
,还有为什么要转义括号?括号的用途是什么?谢谢。谢谢你的深入解释。大家都明白了。开头的
^..*
怎么样?它是否匹配零个或多个非字符或零个或多个字符?如果没有\escape char,会是什么(意思是?我不记得在其他编程语言中需要转义括号,例如Perl/php。答案已经更新。
^.*[/]
表示以零个或多个字符开头的行,此字符序列以
/
-
没有转义字符
\
,表示单个字符:
)。