[英]`find -name` with regex pattern and filename replacement using `cp`
目前我在cron
使用該命令將*.data
從源路徑復制到目標路徑:
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
我需要一個單行解決方案來替換我當前的 cron 命令,以便在執行后,目標將包含:
/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命令打印找到的文件名,每行一個。
read -r filename讀取一行文本並將其存儲到filename變量中。
找到... | 同時 read -r filename all together,將文件名列表(每行一個)寫入管道。 一次只讀取一個文件名。 對於讀取的每個文件名,將執行進入while塊的命令。
sed命令將路徑名/source_path/category1/001.data更改為/target_path/category1_001.data 。
我盡力在下面幾行中解釋sed的字符串參數,但是如果您對這些主題感興趣,則應該閱讀:
s/是搜索和替換 sed 命令,后面跟着 3 個元素:“s/regex pattern/replacement/flag”
^在最開始的意思是,行的開始。
. 表示任何一個字符。
*表示之前指定的字符的 0 或無限個。
[/] 表示一個字符,即字符/ 。 [] 用於轉義/否則它被解釋為正則表達式模式、替換和標志之間的分隔符。
總之^.*[/]表示以任何零個或多個字符開頭的行。 此起始序列必須以/結尾。
[^/] 表示一個字符,開頭的^表示不是列出的字符的一部分。 因此,它意味着除/之外的任何一個字符。
[] 之間的 [abc],表示一個字符:要么 a 要么 b 要么 c。
在正則表達式模式中遇到的第一個\\(.*\\)可以用\\1來替換。 在正則表達式模式中遇到的第二個\\(.*\\)可以用\\2 in replacement來引用。 等等。沒有\\轉義字符, (表示單個字符(
,並且內容不能被引用。
完成后使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.