繁体   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