我是bash脚本的新手,我必须创建这个脚本,它将3个目录作为参数,并在第三个目录中复制第一个中不在第二个目录中的所有文件。
我是这样做的:
#!/bin/bash
if [ -d $1 && -d $2 && -d $3 ]; then
for FILE in [ ls $1 ]; do
if ! [ find $2 -name $FILE ]; then
cp $FILE $3
done
else echo "Error: one or more directories are not present"
fi
我尝试执行它时得到的错误是:“第7行:意外令牌'完成'附近的语法错误” 我真的不知道如何让它发挥作用! 即使我正在使用#!/ bin / bash,我仍然必须在尝试执行时显式调用bash,否则它表示不允许执行,任何人都知道为什么? 在此先感谢:)
答案 0 :(得分:3)
一些建议:
无害双重引用变量
cp "$FILE" "$3" # prevents wordsplitting, helps you filenames with spaces
for
语句失败的根本原因是 - 语法 - 应该是:
for FILE in ls "$1";
但是,从不解析ls
输出。检查[ this ]。
for FILE in ls "$1"; #drastic
而不是第2步中的for-loop
使用find-while-read
组合:
find "$1" -type f -print0 | while read -rd'' filename #-type f for files
do
#something with $filename
done
修改强>
由于您已经提到输入目录只包含文件,我的替代方法是
[[ -d "$1" && -d "$2" && -d "$3" ]] && for filename in "$1"/*
do
[ ! -e "$2/${filename##*/}" ] && cp "$filename" "$3"
done
如果您对${filename##*/}
检查[ shell parameter expansion ]感到困惑。
Sidenote :在linux中,虽然不鼓励使用file name
之类的非标准文件名,但这种情况并不少见。
礼貌:@chepner& @mklement0他们的评论极大地改善了这个答案:)
答案 1 :(得分:1)
你的剧本:
if ...; then
for ...; do
if ...; then
...
done
else
...
fi
固定结构:
if ...; then
for ...; do
if ...; then
...
fi # <-- missing
done
else
...
fi
如果您希望脚本可执行,请将其设为:
$ chmod +x script.sh
请注意,您的脚本中还有其他问题。最好写成
dir1="$1"
dir2="$2"
dir3="$3"
for f in "$dir1"/*; do
if [ ! -f "$dir2/$(basename "$f")" ]; then
cp "$f" "$dir3"
fi
done
答案 2 :(得分:1)
这不完全正确:
for FILE in $(ls $1); do
< whatever you do here >
done
如果在该文件夹中存在如下文件名,则该循环存在一个大问题:'我是一个带有spaces.txt的文件名'。 而不是那个循环尝试这个:
for FILE in "$1"/*; do
echo "$FILE"
done
此外,您必须使用 fi 关闭每个 if 语句。
另一件事,如果您使用BASH(#!/ usr / bin / env bash ),强烈建议您在测试条件中使用双括号:
if [[ test ]]; then
...
fi
例如:
$ a='foo bar'
$ if [[ $a == 'foo bar' ]]; then
> echo "it's ok"
> fi
it's ok
但是,这个:
$ if [ $a == 'foo bar' ]; then
> echo "it's ok";
> fi
bash: [: too many arguments
答案 3 :(得分:-1)
你忘记了最fi
后的if
。
此外,方括号和find
都不会以这种方式工作。这个脚本(就像现在一样)用于我的PC:
#!/bin/bash
if [[ -d "$1" && -d "$2" && -d "$3" ]] ; then
ls -1 "$1" | while read FILE ; do
ls "$2/$FILE" >/dev/null 2>&1 || cp "$1/$FILE" "$3"
done
else echo "Error: one or more directories are not present"
fi
请注意,在单次运行后,当$ 2和$ 3引用不同的目录时,这些文件仍然不在$ 2中,因此下次运行脚本时,它们将再次被复制,尽管它们已经存在于$ 3中。 / p>