我有一個 html 檔案串列,每個檔案中包含某個標簽,如下所示:
<div id="myID" style="display:none">1_34876</div>
我想在每個檔案中搜索該標簽并根據該標簽內的數字重命名每個檔案,即將包含上述標簽的檔案重命名為 1_34876.html 等等。
是否有使用 grep 或 awk 的正則運算式或 bash 命令可以完成此操作?
到目前為止,我能夠使用以下命令 grep 每個檔案,但堅持如何重命名檔案:
grep '<div id="myID" style="display:none">.*</div>' ./*.html
一個額外的好處是,如果該命令不覆寫重復的檔案,例如,如果另一個檔案包含上面的 1_34876 標簽,那么第二個檔案將被重命名為 1_34876 v2.html 或類似的東西。
如果這可以通過不需要編程的方式實作,請提出建議。
確實非常感謝。阿里
uj5u.com熱心網友回復:
您可以使用以下腳本來實作您的目標。請注意,要使腳本在 macOS 上運行,您必須通過 Homebrew 安裝 GNU grep,或者將grep呼叫替換為ggrep.
- 該腳本將在當前目錄及其所有子目錄中搜索
*.html檔案。 - 它將僅替換包含特定標記的檔案的名稱。
- 對于包含相同標簽的多個檔案,除了第一個之外的每個下級檔案都將在其名稱后附加一個識別符號。例如,
1_234.html,1_234_1.html,1_234_2.html - 對于包含多個標簽的檔案,將使用遇到的第一個標簽。
#!/bin/bash
rename_file ()
{
# Check that file name received is an existing regular file
file_name="$(realpath "${1}")"
if [ ! -f "${file_name}" ]; then
echo "No argument or non existing file or non regular file provided"
exit 1
fi
# Get the tag number. If the number does not exist, the variable tag will be
# empty. The first tag on a file will be used if there are multiple tags
# within a file.
tag="$(grep -oP -m 1 '(?<=<div id="myID" style="display:none">).*?(?=</div>)' \
-- "${file_name}")"
# Rename the file only if it contained a tag
if [ ! -z "${tag}" ]; then
file_path="$(dirname "${file_name}")"
# Change directory to the file's location silently
pushd "${file_path}" > /dev/null
# Check for multiple occurences of files with the same tag
if [ -e "${tag}.html" ]; then
counter="$(find ./ -maxdepth 1 -type f -name "${tag}.html" -o -name "${tag}_*.html" | wc -l)"
tag="${tag}_${counter}"
fi
# Rename the file
mv "${file_name}" "${tag}.html"
# Return to previous directory silently
popd > /dev/null
fi
}
# Necessary in order to call rename_file from find command within main
export -f rename_file
# The entry point function of the script. This function searches for all the
# html files in the directory that the script is run, and all subdirectories.
# The function calls rename_files upon each of the found files.
main ()
{
find ./ -type f -name "*.html" -exec bash -c 'rename_file "${1}"' _ {} \;
}
main
uj5u.com熱心網友回復:
由于我們不知道我們需要注意的檔案和檔案夾的確切內容
- 檢查標簽是否唯一
- 同名檔案不存在
- 不要重命名已重命名的檔案
腳步:
- 搜索帶有指定標簽的檔案,
grep -o '<div id="myID" style="display:none">.*</div>' /*.html它將為我們提供格式輸出file_path:tag - 使用正則運算式
[^:](不是:一個或多個符號)和-o(完全匹配)提取 file_path并使用head -1 - 使用正則運算式 ">. <"從標簽中獲取新檔案名,然后使用 sed 洗掉 "<>" 我們可以在這里使用一個正則運算式來跳過 <>,但它會更復雜,而且不那么可讀 grep -oP ">\K。 (?=<)"
- 重命名檔案,記錄錯誤和腳本操作,在出現問題時回傳非零退出代碼
- 除非真的好需要與區域變數宣告中使用的功能(decalre使用
function fn_rename_html_files {},而不是fn_rename_html_files() {}作為如果我們有嵌套功能復雜的邏輯,你可能會改變其他函式的變數和除錯將是不那么容易)
function fn_rename_html_files {
typeset l_files_path="${1-.}"
typeset l_html_ext=".html"
typeset l_proc_exit_code=0
typeset l_proc_name="${FUNCNAME[0]}"
typeset l_files_to_search="${l_files_path}/*${l_html_ext}"
typeset l_tag_reg_exp='<div id="myID" style="display:none" *>.*</div>'
typeset l_matched_files=$(grep -o "$l_tag_reg_exp" $l_files_to_search | sort -u)
typeset l_prev_file_path=""
# loop through matching files
while IFS= read -r l_file_path_with_match_tag
do
l_current_file_path=$(echo "$l_file_path_with_match_tag" | egrep -o "([^:]) " | head -1 )
l_current_file_name=$(basename "$l_current_file_path")
#echo "l_current_file_path $l_current_file_path "
#echo "l_current_file_name $l_current_file_name "
l_new_file_name_from_tag=$(echo "$l_file_path_with_match_tag" | egrep -o ">.*<" | sed "s/[><]//g" | head -1 )
l_new_file_name="${l_new_file_name_from_tag}${l_html_ext}"
l_new_file_path="$l_files_path/$l_new_file_name"
#echo "$l_new_file_path $l_new_file_path "
#echo "$l_new_file_name $l_new_file_name "
if [[ "$l_prev_file_path" == "$l_current_file_path" ]]; then
echo "$l_proc_name ERROR: myID tag is not unique for $l_current_file_path, skipping second renaming " >&2
let l_proc_exit_code =1
continue
fi
if ! [[ -f "$l_new_file_path" ]]; then
if mv "$l_current_file_path" "$l_new_file_path" ; then
echo "$l_proc_name SUCCESS: renamed $l_current_file_path to $l_new_file_path"
else
echo "$l_proc_name ERROR: cannot move $l_current_file_path to $l_new_file_path" >&2
let l_proc_exit_code =1
fi
else
if [[ "$l_current_file_name" == "$l_new_file_name" ]]; then
echo "$l_proc_name Warning: File has been already renamed: $l_current_file_name, skipping"
else
echo "$l_proc_name Warning: File with such name already exists: $l_current_file_name, skipping" >&2
let l_proc_exit_code =1
fi
fi
l_prev_file_path=$l_current_file_path
done <<< $l_matched_files
return $l_proc_exit_code
}
# create test files
rm *.html
echo '<div id="myID" style="display:none">1_1</div>' > 1.html ;
echo '<div id="myID" style="display:none">1_2</div>' > 2.html ;
echo '<div id="myID" style="display:none">1_3</div>' > 3.html ;
echo '<div id="myID" style="display:none">1_3_1</div>' >> 3.html ;
# run
fn_rename_html_files

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314066.html
上一篇:需要幫助資料以進行發票資料輸入
