[英]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
来确保它是一个常规文件)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.