クリーニング時に.bakファイルを生成する簡単なコードがあります。再クリーンアップすると、bak ファイルが削除され、.bak ファイルがなくなります。 bak "no .bak"を表示する必要がありますが、if条件のみを実行します。コードは次のとおりです。
#!/bin/bash
chmod u+x sources/*
if [ "$1" == "clean" ]
then
if [ -f `sources/*.bak` ]
then
rm sources/*.bak
else
echo "there's no .bak files"
fi
elif ["" == "$1"]
then
echo "This script makes a backup for each .c or .h file in sources directory"
target_files=`echo -n $(ls sources/{*.c,*.h})`
echo
echo "Starting to backup: $target_files"
for i in $target_files
do
cp "$i" "$i".bak
done
echo
echo "The following backup files were created: `echo -n $(ls sources/*.bak)`"
echo
echo "Done"
fi
答え1
問題はラインです
if [ -f `sources/*.bak` ]
バックティックは`
bashで特別な意味を持ちます。これは、コマンドを評価してその出力を返すために使用されます。
たとえば、ユーザー名が次のような場合プロそれから
if [ -f `whoami` ]
という存在があることを確認してくださいfrodl
。
したがって、を書くと、sources/*.bak
最初に用語をglobしようとしますが、sources/*.bak
ディレクトリに拡張子を持つファイルがないため、用語は拡張されません。次に、有効なコマンドではなくリテラル用語を実行しようとします(実際にはsources/
.bak
sources/*.bak
できる(最初にアスタリスクがあるファイル名; shudder!)というファイルがありますがsources/*.bak
、ないようです。ただし、このファイルには.bak
以前に除外した拡張子があります。 )
ファイルが存在する場合は、sources/deletemyharddisk.bak
用語をsources/*.bak
その文字列に展開してから実行しようとします(ハードドライブが消去される可能性があります)。
したがって、やるべきことは一般的な引用符を使用することだけです。
backupfiles=sources/*.bak
if [ "x${backupfiles}" = "xsources/*.bak" ]; then
echo "no .bak files" 1>&2
else
echo "there are .bak files"...
fi
まず、用語を変数sources/*.bak
に拡張しようとします。backupfiles
bakファイルがある場合は、すべてのファイル名の文字列になります。ファイルが存在しない場合、文字列は拡張されていません。次に、結果をリテラル(拡張されていない)と比較すると、一致するファイルがあるためにsources/*.bak
拡張が発生したかどうかがわかります。
より良い方法
しかし、最初にファイルが存在することを確認してから削除する理由はありません。より簡単なアプローチは、特定のパターンに一致するすべてのファイルを削除することです。
find
あなたのためにこれを行うことができます:
find sources/ -maxdepth 1 -type f -name "*.bak" -delete
-maxdepth 1
(これを行うと、ディレクトリ()の最初のレベルでsources/
()で終わるファイルを検索します(-type f
;ディレクトリやシンボリックリンクなどではありません)。その後、そのファイルを削除します()。.bak
-name "*.bak"
-delete
解析されないls
コードのもう一つの問題は
target_files=`echo -n $(ls sources/{*.c,*.h})`
for i in $target_files
...
あなたはする必要があります解析されない出力ls
。
代わりに、次のようなものを使用してください。
for i in sources/*.c sources/*h
do
#...
done