簡體   English   中英

Bash 文件名不會 append 從腳本文件

[英]Bash File names will not append to file from script

您好,我正在嘗試將所有帶有 Jane 名字的文件保存到一個名為 oldFiles.txt 的單獨文件中。 在一個名為“data”的目錄中,我正在從一個名為 list.txt 的文件中讀取文件名列表,我從該文件中將包含名字 Jane 的所有文件名放入文件變量中。 然后我嘗試用 list.txt 中的文件測試文件變量以確保它們在文件系統中,然后 append 所有包含 jane 的文件到 oldFiles.txt 文件(將在腳本目錄中),在測試以確保文件變量中的項目通過之后。

#!/bin/bash

> oldFiles.txt
files= grep " jane " ../data/list.txt | cut -d' ' -f 3
if test -e ~data/$files; then
  for file in $files; do
    if test -e ~/scripts/$file; then
      echo $file>> oldFiles.txt
    else
      echo "no files"
    fi
  done
fi

上面的代碼獲取所需的文件並正確顯示它們,並創建了 oldFiles.txt 文件,但是當我在運行腳本后打開文件時,我發現沒有任何內容附加到文件中。 我嘗試將文件分配改為指針files= grep " jane "../data/list.txt | cut -d' ' -f 3 ---> files=$(grep " jane "../data/list.txt) files= grep " jane "../data/list.txt | cut -d' ' -f 3 ---> files=$(grep " jane "../data/list.txt)以查看僅捕獲原始數據以寫入文件是否有幫助,但隨后出現錯誤向上“第 5 行太多 arguments”,這是第一個 if 測試語句。 讓腳本半正常工作的唯一方法是在 shell 命令行上執行./findJane.sh > oldFiles.txt ,這實際上是我手動創建文件。 我將如何對此進行 go 以便我在腳本中創建 oldFiles.txt 和 append 到 oldFiles.txt?

據我所知,這就是你想要的。 這完全是基於評論的社區努力,捕捉你的錯誤。 顯然要歸功於 Mark 和 Jetchisel 發現了大部分問題。 顯着變化:

  • 修復$files以使用命令替換
  • data/$file的固定路徑,假設你在~/data有一個充滿文件的目錄
  • 修復了測試,不測試一串文件,而只測試單個文件(也使用-f來確保它是一個常規文件)
  • 使用雙括號——你也可以使用雙引號代替,但你明確地有一個 Bash shebang 所以使用 Bash 語法沒有壞處
  • 添加關於不匹配文件的第二條消息,因為那里有兩種可能的情況; 您可能需要根據您要查找的 output 進行調整
  • 刪除了初始的空重定向——如果你需要確保文件在腳本的 rest 之前是清晰的,那么它應該被添加回來,但如果不是,它就沒有做任何有用的工作
  • 更改了 shebang 以確保您使用的是用戶首選的 Bash,並添加了set -e因為您應該始終添加set -e
#!/usr/bin/env bash
set -e

files=$(grep " jane " ../data/list.txt | cut -d' ' -f 3)
for file in $files; do
    if [[ -f $HOME/data/$file ]]; then
        if [[ -f $HOME/scripts/$file ]]; then
            echo "$file" >> oldFiles.txt
        else
            echo "no matching file"
        fi
    else
        echo "no files"
    fi
done

你遇到的最大問題是匹配名稱,如"jane""Jane's"等,而不匹配"Janes" grep提供了選項-i (不區分大小寫的匹配)和-w (全字匹配),它們可以根據您想要的內容定制您的搜索,而無需使用在搜索前后添加空格的笨拙( " jane " )學期。 (要正確地做到這一點,你會使用[[:space:]]jane[[:space:]]

如果您從包含腳本的目錄以外的目錄調用腳本,例如使用bash script/findJane.sh$HOME目錄調用腳本,您還會遇到"script dir"是什么的問題。 在這種情況下,您的腳本將嘗試 append 到$HOME/oldFiles.txt 位置參數$0始終包含當前正在運行的腳本的完整路徑名,因此無論您從何處調用腳本,都可以捕獲腳本目錄:

dirname "$0"

您正在使用 bash,因此將grep命令產生的所有文件名存儲在一個數組中,而不是一些通用變量(特別是因為您使用" jane "表明您的文件名包含空格)

如果您獲取輸入文件的信息(例如list.txt )、要搜索的術語(例如"jane" )、檢查文件是否存在的位置(例如$HOME/data )和 output 文件名到 append 名稱(例如"oldFile.txt" )作為命令行 [positonal] 參數。 您可以給每個默認值,使其按照您當前的期望運行,而無需提供任何 arguments。

即使使用命令行 arguments 的額外腳本靈活性,腳本實際上有更少的行,只需使用mapfile (與readarray同義)填充數組,然后遍歷數組的內容。 您還可以通過簡單的參數擴展來避免dirname的附加子 shell,並測試路徑組件是否為空——替換為'.' , 由你決定。

如果我正確理解了您的目標,您可以將所有部分放在一起:

#!/bin/bash

# positional parameters
src="${1:-../data/list.txt}"  # 1st param - input (default: ../data/list.txt)
term="${2:-jane}"             # 2nd param - search term (default: jane)
data="${3:-$HOME/data}"       # 3rd param - file location (defaut: ../data)
outfn="${4:-oldFiles.txt}"    # 4th param - output (default: oldFiles.txt)

# save the path to the current script in script
script="$(dirname "$0")"

# if outfn not given, prepend path to script to outfn to output
# in script directory (if script called from elsewhere)
[ -z "$4" ] && outfn="$script/$outfn"

# split names w/term into array
# using the -iw option for case-insensitive whole-word match
mapfile -t files < <(grep -iw "$term" "$src" | cut -d' ' -f 3)

# loop over files array
for ((i=0; i<${#files[@]}; i++)); do
  # test existence of file in data directory, redirect name to outfn
  [ -e "$data/${files[i]}" ] && printf "%s\n" "${files[i]}" >> "$outfn"
done

(注意: test expression[ expression ]是同義詞,使用你喜歡的,盡管你可能會發現[ expression ]更具可讀性)

(進一步注意: "Janes"作為復數並不被認為與單數相同——根據需要調整grep表達式)

示例使用/輸出

正如評論中指出的那樣,如果沒有您的輸入文件樣本,我們無法提供准確的測試來確認您想要的行為。

如果您有任何疑問,請告訴我。

暫無
暫無

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

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