私はLinuxを学んでいますが、この質問を宿題にしていますが、シェルモードで2つのファイルの内容を比較する方法に関する問題は解決できません。 (ここでは、両方のファイルがこのようなテキストコンテンツを持っていると仮定できます。たとえば、ファイル1の$ cat> f1)
$ cat duplicate_file.sh
echo "Enter file 1:"
read file1
echo "Enter file 2:"
read file2
cmp $file1 $file2 > newfile
x=` wc newfile | cut -d" " -f2 `
if [` $x -eq 0 `]
then
rm -i $file2
fi
このプログラムを書きましたが、うまくいきません!それでは提案がありますか?
答え1
コードの即時の問題は、読み出し行の構文エラーです。
if [` $x -eq 0 `]
[
との引数はスペース文字で]
区切る必要があります。また、その行のコマンド置換は値をコマンドとして実行しよ`$x -eq 0`
うとするため、意味がありません。$x
また、スクリプトが空白文字とファイル名のグロービングパターンを含むファイル名を処理できないという引用符なしの変数拡張の問題もあります。
また、スクリプトは無条件にファイルを不必要に破損させ(newfile
既存のディレクトリ名の場合は失敗します) - 行がありません。newfile
#!
ユーザーに対話的にファイルパスを要求することは意味がありません。ユーザーは、コマンドラインでシェルのファイル名補完を使用して、ファイルのパス名を両方のオペランドとして指定することをお勧めします。
$ ./script.sh some/path/file1 some/other/path/file2
この方法でスクリプトを実行すると、スクリプト内とという"$1"
2つのパス名を使用できます"$2"
。
cmp
実用的な事項一時ファイルを作成しなくても、このスクリプト内で使用できます。出力をリダイレクトするのではなく、対応するオプション(「silent」)を使用して自動的に作成し、終了ステータスを-s
使用して2つのファイルが同じであることを確認します。
スクリプトは次のとおりです。
#!/bin/sh
if cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
またはより短く、
#!/bin/sh
cmp -s -- "$1" "$2" && rm -i -- "$2"
rm -i
参照するファイルの内容が最初のパス名と同じ場合、指定された2つのパス名のうち2番目のパスを呼び出します。--
ダッシュで始まるファイル名をオプションセットとして解釈したくない場合は、コマンドが必要です。cmp
rm
これ質問このスクリプトを提供する場合は、独自のスクリプトのように使用してください。同じパス名が2回つまり、ファイルを自分と比較すると削除を提案します。
したがって、両方のパス名が両方のパスを参照していることを確認する必要があります。その他文書。
2つのパス名文字列を比較することでこれを行うことができます。
#!/bin/sh
if [ "$1" != "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
./file
これは一部のアプリケーションでは十分ですが、他のパス(vs file
vs/path/to/file
など)で指定されたシンボリックリンクやファイルは考慮されません。ほとんどのシェルでは非標準(しかし、)-ef
テスト(「同じファイル」)は、2つのパス名が同じファイルを参照するかどうかをテストします(同じinode番号とデバイスなので、同じファイルへの2つのハードリンクに対してもtrueを返します)。
#!/bin/bash
if ! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2"; then
rm -i -- "$2"
fi
または、
#!/bin/bash
! [ "$1" -ef "$2" ] && cmp -s -- "$1" "$2" && rm -i -- "$2"
そして、いくつかの完全性チェックを実行します(また、-ef
テストを完全性チェックセクションに移動します)。
#!/bin/bash
if [ "$#" -ne 2 ]; then
# did not get exactly two arguments
printf 'Usage:\n\t%s file1 file2\n' "$0" >&2
exit 1
elif [ ! -f "$1" ] || [ ! -f "$2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$1" -ef "$2" ]; then
printf '%s and %s refer to the same file\n' "$1" "$2" >&2
exit 1
fi
cmp -s -- "$1" "$2" && rm -i -- "$2"
パス名にスペースが含まれることは珍しくないため、引用変数の拡張が重要です(macOSではこれは一般的です)。また、二重引用符変数拡張は、その変数がシェルグローブパターンとして解釈されるのを防ぎます(たとえば、コードは名前付きファイルでは実行されません*
)。また、#!
スクリプトで-lineを適切に使用したことを確認してください。
宿題なら必要対話的に2つのファイルのパス名を読み取り、合計を空の文字列にread -r
設定します。IFS
これにより、スペースまたはタブで始まるか終わり、文字を含むパス名を読み取ることができます\
(改行文字を含むパス名は指定できません)。
#!/bin/bash
IFS= read -p '1st pathname: ' -r p1
IFS= read -p '2nd pathname: ' -r p2
if [ ! -f "$p1" ] || [ ! -f "$p2" ]; then
echo 'One of the files does not exist (or is not a regular file)' >&2
exit 1
elif [ "$p1" -ef "$p2" ]; then
printf '%s and %s refer to the same file\n' "$p1" "$p2" >&2
exit 1
fi
cmp -s -- "$p1" "$p2" && rm -i -- "$p2"
関連:
自分のコードのように、ある時点でファイルが空であることを確認する必要がある場合は、wc
そのファイルを呼び出さないでください(ファイル全体を読む必要があるため、非効率的です)。代わりに-s
テストを使用してください。
if [ -s "$pathname" ]; then
printf '%s has non-zero size\n' "$pathname"
else
printf '%s is empty (or does not exist)\n' "$pathname"
fi
man test
システムを参照するか、以下を参照してください。このユーティリティのPOSIX規格。
答え2
#!
たとえば、上部にshebangを追加することから始めます。#!/bin/bash
2つのエラーがあります。
変える
cmp $file1 $file2 > newfile,
しなければならない
cmp -- "$file1" "$file2" > newfile
なぜなら、これらの変数の値には、スペース、タブ、改行(文字$IFS
)、、、*
(ワイルドカード文字)を含めることができ、またはで[
始めることができるからです。?
-
2番目のエラー:
変える
if [` $x -eq 0 `]
しなければならない
if [ "$x" -eq 0 ].
それ以外の場合はエラーが発生します
bash:0:コマンドが見つかりません。
また、ファイル名にスペースまたはワイルドカードがある場合は、次のようにする必要があります。
rm -i -- "$file2"
そうしないと、複数のファイルが削除される可能性があります。
答え3
これが私の実装です。
#! /bin/bash
echo -n "Enter file1: "
read file1
echo -n "Enter file2: "
read file2
if cmp -s -- "$file1" "$file2"
then
echo same
rm -i -- "$file2"
else
echo different
fi
var1.txt
、、、var2.txt
3つのファイルがありますvar3.txt
。
var1
違いはvar2
var2
同じですか?var3
これらのファイルに対して上記のスクリプト(com.sh
)を実行すると、次の結果が得られます。
$ bash com.sh
Enter file1: var1.txt
Enter file2: var2.txt
different
$ bash com.sh
Enter file1: var2.txt
Enter file2: var3.txt
same
rm: remove regular file 'var3.txt'?
答え4
次のコードは、出力が空でnull
あることを確認します。空の場合、ファイルは同じで、そうでなければファイルは異なります。
output=`echo | cmp -b $file1 $file2`
if [[ -z $output ]]
then
echo "Same"
rm $file2
else
echo "Diff"
fi