我注意到运算符“>>”在我的脚本中不能很好地工作,我不知道为什么。我有一个这样的脚本:
for file in $(ls folder)`
do
echo $file >> text.txt
done
进入文件夹我得到了 91 个元素,但只插入了前 87 个元素文件.txt。我无法弄清楚这段代码有什么问题,有人可以帮助我理解吗?
编辑
我在那里写的脚本非常简单,但我知道它并没有清楚地描述情况。所以,这里有更多详细信息:
在我的文件夹中,我收到了 91 个 csv 文件,每个文件包含两列:名称和值。对于每个文件,我需要控制该值是否大于 2.500,以及是否不为 0.000。如果这两个条件之一为真,我会将文件名及其值附加到包含我丢弃的文件的 txt 文件中,否则我将文件名及其值附加到包含我选择的文件的 csv 文件中。我用来控制值的代码运行良好,但是当我使用 >> 将结果附加到 txt 或 csv 文件中时,最后四个结果不会附加,我无法理解为什么。
for file in $(ls folder)
do
value=$(cat path/$file | awk -F, '{print $2}')
discard=$(awk -v num1="$value" 'BEGIN { if (num1 > 2.500) print 1; else if (num1 == 0.000) print 0; else print 2 }')
if [[ $discard -eq 1 || $discard -eq 0 ]]
then
echo ""$file" has value="$value"" >> path/discard.txt
rm path/"$file"
else
echo ""$file",$value" >> path/selected.csv
rm path/"$file"
fi
done
这是我的脚本的更完整版本。
编辑2
我更正了我的脚本以解决您在其中发现的问题。还是同样的问题。更清楚地说,我的文件夹中的文件是由程序自动生成的 csv 文件,它们仅包含一行 2 列:一个 ID 和一个浮点值。它们都非常相似,所以问题不在那里,因为我可以从终端看到脚本识别它们并很好地处理它们。我仍然不知道为什么append不将最后4个四个文件放入txt文件中。
for file in folder/*
do
value=$(cat "$file" | awk -F, '{print $2}')
discard=$(awk -v num1="$value" 'BEGIN { if (num1 > 2.500) print 1; else if (num1 == 0.000) print 0; else print 2 }')
if [[ "$discard" -eq 1 || "$discard" -eq 0 ]]
then
echo ""$file" has value="$value"" >> path/discard.txt
rm -- "$file"
else
echo ""$file",$value" >> path/selected.csv
rm -- "$file"
fi
done
减少文件数量,顺便说一句,它工作得很好。
答案1
这里有两个主要问题:
永远不会做
for file in $(ls)
。这也称为bash 陷阱第 1 号。首先,它很脆弱,正如您所看到的,即使是稍微奇怪的文件名也会损坏。更糟糕的是,根本不需要它,它只会使代码比需要的更脆弱、更复杂。你可以这样做for file in *
。始终引用您的变量。当处理可能包含以下内容的文件名时,这一点尤为重要任何字符除外
\0
。和/
。如果不引用变量,shell 将扩展该变量,因此如果它包含空格,shell 将看到两个值而不是一个。例如:
为了说明这一点,请考虑一个包含这两个文件的目录:
$ touch 'a file2' 'file1 *'
$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Sep 22 17:39 'file1 *'
-rw-r--r-- 1 terdon terdon 0 Sep 22 17:39 'a file2'
现在,如果我们尝试您的原始代码,我们会得到:
$ for file in $(ls); do echo $file; done
a
file2
file1
a file2
file1 a file2 file1 *
这是因为,由于您没有引用,外壳程序会收到a
, file2
, thenfile1
和 then *
。因此它会单独处理每个文件,并在最后运行时echo *
再次打印目录中的所有内容。但是,如果您以正确的方式进行操作,那么一切都会有效:
$ for file in *; do echo "$file"; done
a file2
file1 *
这是脚本的工作版本(首先测试一下,我看不到您的数据):
for file in folder/*
do
value=$(awk -F, '{print $2}' "$file")
discard=$(awk -v num1="$value" 'BEGIN { if (num1 > 2.500) print 1; else if (num1 == 0.000) print 0; else print 2 }')
if [[ $discard -eq 1 || $discard -eq 0 ]]
then
printf '"%s" has value="%s"' "$file" "$value" >> path/discard.txt
rm -- "$file"
else
printf '"%s",%s' "$file" "$value" >> path/selected.csv
rm -- "$file"
fi
done
答案2
我只是尝试使用 CSV 文件而不是 TXT 文件来处理丢弃的元素。现在脚本运行良好。
for file in folder/*
do
value=$(cat "$file" | awk -F, '{print $2}')
discard=$(awk -v num1="$value" 'BEGIN { if (num1 > 2.500) print 1; else if (num1 == 0.000) print 0; else print 2 }')
if [[ "$discard" -eq 1 || "$discard" -eq 0 ]]
then
echo ""$file" has value="$value"" >> path/discard.csv
rm -- "$file"
else
echo ""$file",$value" >> path/selected.csv
rm -- "$file"
fi
done
感谢大家的帮助和建议!