簡體   English   中英

bash:擴展參數列表並將其傳遞以查找-轉義/空格地獄

[英]bash: Expand list of arguments and pass it to find - escaping/white spaces hell

我想檢查文件夾中的文件並刪除其中的一些文件。 一個條件是保留所有某種類型的文件(例如.txt),並且還保留所有具有第一次搜索名稱但具有不同擴展名([第一次搜索的名稱] )的文件。 目錄中的所有其他文件都應刪除。

通過find . -type f -not -name xxx可以輕松實現find . -type f -not -name xxx find . -type f -not -name xxx命令。 但是,我想為每個自動找到的[首次搜索的名稱]填充find命令。

為此,我編寫了這個小腳本

#!/bin/bash

while read filename; do
     filename=$(echo $filename | sed 's/\ /\\\ /g')
     filename=\'$filename*\'
     file_list=$file_list" -not -name $filename"
done <<<"$(ls *.txt | sed 's/.txt//g')"

find . -type f $file_list -print0| while read -d $'\0' FILE
     do
     rm -f "$FILE"
done

$ file_list很好地填充了各自的數據,但是,發現失敗說:

查找:未知謂詞“-\\”

萬一我使用sed命令(''->'\\')或

查找:路徑必須在表達式之前:-用法:查找[-H] [-L] [-P] [-Olevel] [-D [help | tree | search | stat | rates | opt | exec] [path ... ] [表情]

如果我評論sed行。

bash -x向我顯示了以下已執行的命令:

沒有sed命令:

找 。 -type f -not -name``\\''Text'-here-or-there *'\\'''

使用sed命令:

找 。 -type f -not -name``\\''Text \\''-\\''here \\''-\\''or \\''there *'\\'''

使用find甚至可能嗎? 我也嘗試在find命令中轉義$find_list ,但沒有成功。

使用數組,而不是字符串。

#!/bin/bash
# ^-- must be /bin/bash, not /bin/sh, for this to work

excludes=( )
for filename in *.txt; do
  excludes+=( -not -name "${filename%.txt}" )
done

find . -type f -not -name '*.txt' "${excludes[@]}" -exec rm -f '{}' +

要了解其工作原理,請參閱BashFAQ#50


現在,如果您想與/bin/sh兼容,而不僅僅是bash,則將其封裝在一個函數中,這樣您就可以覆蓋參數列表(這是唯一可用的數組),而不會丟棄腳本的全局參數:

delete_except_textfiles() {
  local filename 2>/dev/null ||: "local keyword not in POSIX, ignore if not present"
  set --
  for filename in *.txt; do
    set -- "$@" -not -name "${filename%.txt}"
  done
  find . -type f -not -name '*.txt' "$@" -exec rm -f '{}' +
}
delete_except_textfiles

嘗試這個

#!/bin/bash

remove_except()
{
    local extension=$( printf "%q" "$1" )
    local dir=$( printf "%q" "$2" )
    local start_dir=$(pwd)

    [ -z "$extension" ] && return 1
    [ -z "$dir" ] || [ ! -d "$dir" ] && dir="."
    cd "$dir"

    local this="$0"
    this="${this##*/}"

    # exclude myself and extension
    local excludes=" -name \"$this\" -o -name \"*.$extension\" "

    for f in *."$extension";
    do
        filename="${f%.*}"
        excludes="$excludes -o -name \"$filename.*\""
    done

    eval "find . -maxdepth 1 -type f -not \( $excludes \) -print0" | xargs -0 -I {} rm -v {}

    cd "$start_dir"
}

remove_except "txt" "/your/dir"

放入腳本,例如remove_except.sh ,然后像這樣運行它:

remove_except.sh "txt" "/your/dir"

第二個參數是可選的,將采用. 如果未指定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM