【问题标题】:Script does not work with ` but works in single command脚本不能与 ` 一起使用,但可以在单个命令中使用
【发布时间】:2021-05-05 08:32:17
【问题描述】:

在我的 bash 中,整个脚本都不起作用...当我使用 `

我的脚本是

#!/bin/bash

yesterday=$(date --date "$c days ago" +%F)

while IFS= read -r line
do

dir=$(echo $line | awk -F, '{print $1 }')
country=$(echo $line | awk -F, '{print $2 }')

cd path/$dir

cat `ls -v | grep email.csv` > e.csv 

done < "s.csv"

上面的输出是空白的。

如果我使用“”

输出是No such file or directory

但如果我在终端上只使用 1 行,它就可以工作

cat `ls -v | grep email.csv` > e.csv 

我也尝试使用 / ,但也没有用...

【问题讨论】:

  • 将您的代码复制/粘贴到shellcheck.net,修复它告诉您的问题,然后让我们知道您是否仍有问题并发布更正后的代码。

标签: bash awk


【解决方案1】:

你一般应该avoid ls in scripts.

此外,您通常应该更喜欢现代 POSIX $(command substitution) 语法,就像您已经在脚本中的其他几个地方所做的那样;过时的反引号 `command substitution` 语法笨拙,更容易出错。

如果这在当前目录中有效但在其他目录中失败,则表示您在当前目录中有一个与正则表达式匹配的文件,但在其他目录中没有。

无论如何,做你正在尝试的事情的惯用方法就是

cat *email?csv* >e.csv

如果您要匹配文字点,那就是正则表达式中的\.? 是对您的 grep 实际上 所做的事情的字面解释;但在下文中,我将假设您实际上是要匹配 *email.csv*(或者实际上可能甚至可能是 *email.csv 而没有尾随通配符)。

如果你想检查是否有任何文件,如果没有则避免创建e.csv,这有点棘手;可以试试

for file in *email.csv*; do
    test -e "$file" || break
    cat *email.csv* >e.csv
    break
done

或者,查看 Bash 的 nullglob 功能。另见Check if a file exists with wildcard in shell script

另一方面,如果您只想检查email.csv 是否存在,不使用通配符,这很容易:

if [ -e email.csv ]; then
    cat email.csv >e.csv
fi

事实上,这甚至可以简写为

test -e email.csv && cat email.csv >e.csv

顺便说一句,read 可以完美地将一行拆分为标记。

#!/bin/bash

yesterday=$(date --date "$c days ago" +%F)

while IFS=, read -r dir country _
do
    cd "path/$dir"   # notice proper quoting, too
    cat *email.csv* > e.csv
    # probably don't forget to cd back
    cd ../..
done < "s.csv"

如果这实际上是您的脚本所做的所有事情,那么可能会取消愚蠢且容易出错的cd

while IFS=, read -r dir country _
do
    cat "path/$dir/"*email.csv* > "path/$dir/e.csv"
done < "s.csv"

另见When to wrap quotes around a shell variable

【讨论】:

  • 我在开玩笑...实际代码太长了..如果我在这里用 ls 更改,我需要做很多更改...但是使用 break 的那个对我来说是新的...在循环中我从不做 cd 回来。因为每次循环运行我第一次通过完整路径进入目录...
  • 如果你想在不需要任何通配符的情况下检查文字文件名email.csv,那就容易多了;立即查看更新的答案。另请参阅关于在结尾处完全避免 cd 的说明。
最近更新 更多