1. 概要

Linuxには、ファイルを操作できる便利なコマンドが多数用意されています。

このクイックチュートリアルでは、Linuxコマンドラインで2つのファイルを交換する方法について説明します。

2. 問題の紹介

まず、「2つのファイルを入れ替える」とはどういう意味かを明確にしましょう。 ここでは、2つのファイルの場所を入れ替えることについては話していません。 代わりに、2つのファイルのコンテンツを交換します

例は、問題をすばやく理解するのに役立つ場合があります。 2つの異なるディレクトリに2つのファイルがあるとしましょう。

$ head /home/kent/test/**/*.txt
==> /home/kent/test/dir1/file1.txt <==
I am file1

==> /home/kent/test/dir2/file2.txt <==
I am file2

ここで、2つのファイルを交換した後、次のようにします。

==> /home/kent/test/dir1/file1.txt <==
I am file2

==> /home/kent/test/dir2/file2.txt <==
I am file1

2つのファイルの内容が交換されていることに注意してください。

それは難しい仕事ではありませんが、それを行うための効率的で安全な方法に取り組みます。

3. mvコマンドの使用

すでに知っているように、多くのプログラミング言語で2つの変数の値を交換する一般的な方法は、一時変数を使用することです。

temp = a
a = b
b = temp

同様に、同じ考えでファイルを交換することができます。 ただし、 temp 変数の代わりに一時ファイルを使用し、mvコマンドを「割り当て」操作として使用します。

mv FILE1 TMP
mv FILE2 FILE1
mv TMP FILE2

3つのステップは非常に簡単です。 ただし、注意が必要な点がいくつかあります

  • TMPファイルを保存する場所
  • いずれかのステップでエラーが発生した場合でも、データを失うことはありません

次に、2つの項目を詳しく見ていきましょう。

一時ファイルの作成について話すとき、私たちの直感は /tmpディレクトリにつながる可能性があります。 その名前が示すように、一時ファイルを保存するのに最適な場所です。

ただし、すべてのユーザーが/tmpディレクトリの下のファイルにアクセスできます。 したがって、機密データを含むファイルをそこに置くと、特にパブリックサーバーでセキュリティリスクが発生します。 これを防ぐために、 TMPファイルをFILE1と同じ場所に保存するか、 FILE2。 したがって、アクセスできるユーザーのみがアクセスできます。 FILE1 また FILE2。 したがって、セキュリティ上のリスクはありません。

3つのmvコマンドはアトミックな方法では機能しません。 つまり、それらのいずれかが失敗した場合、ロールバック操作はトリガーされません。 とにかくトランザクション操作ではないので、受け入れることができます。 ただし、最終的には、エラーが発生してもデータが失われることはありません。

たとえば、FILE1のディレクトリの下にTMPを最初に作成すると、IOの障害が原因で失敗する場合があります。 この場合、それ以上のコマンドで予期しないファイルの上書きが発生することは望ましくありません。 それを達成するために、 コマンドを「&&」で連結します 。 それの訳は &&演算子は、前のコマンドが成功した場合にのみ、後のコマンドが実行されるようにします

それでは、この例でテストしてみましょう。

$ mv /home/kent/test/dir1/file1.txt /home/kent/test/dir1/tmp.file1 && \
    mv /home/kent/test/dir2/file2.txt /home/kent/test/dir1/file1.txt && \
    mv /home/kent/test/dir1/tmp.file1 /home/kent/test/dir2/file2.txt

$ head /home/kent/test/**/*.txt
==> /home/kent/test/dir1/file1.txt <==
I am file2

==> /home/kent/test/dir2/file2.txt <==
I am file1

上記の出力が示すように、コマンドは機能します。 2つのファイルの内容を入れ替えました。

ただし、欠点は明らかです。コマンド全体を手動で入力する必要があります。 作成しようとしている一時ファイルが存在しないため、オートコンプリートはファイル名を完成させるのに役立ちません。 そこにタイプミスがあると、一部のファイルが失われる可能性があります。

したがって、longコマンドをラップする関数を作成しましょう。

4. 再利用可能な関数の作成

理想的には、関数は2つの引数を取ることができます。これは、2つのファイルの絶対パスです。 さらに、一時ファイルを自動的に生成する必要があります。

function swapFiles() {
    if (( $# == 2)) ; then
        TMPFILE=$(mktemp $(dirname "$1")/XXXXXX)
        mv "$1" $TMPFILE && mv "$2" "$1" && mv $TMPFILE "$2"
    else
        echo "Error: Two valid file paths required"
        return 1
    fi
}

それでは、関数を入手して、それが機能するかどうかをテストしましょう。

$ head /home/kent/test/**/*.txt
==> /home/kent/test/dir1/file1.txt <==
I am file1

==> /home/kent/test/dir2/file2.txt <==
I am file2

$ swapFiles /home/kent/test/dir1/file1.txt /home/kent/test/dir2/file2.txt

$ head /home/kent/test/**/*.txt
==> /home/kent/test/dir1/file1.txt <==
I am file2

==> /home/kent/test/dir2/file2.txt <==
I am file1

上記の出力からわかるように、関数は期待どおりに機能します。

また、スワップしたい2つのファイルを引数として指定することもできます。 関数は残りすべてを処理します。 この場合、Bashのオートコンプリートは私たちに大いに役立ちます。

次に、関数をすばやく見て、どのように機能するかを理解しましょう。

  • mktemp コマンドを使用して、ランダムな名前の一時ファイルを作成しました。
  • 一時ファイルが最初の入力ファイルと同じディレクトリにあることを確認するために、 dirname“ $ 1” コマンドを使用して、最初のファイルの親ディレクトリを取得しました。

関数では、簡単にするために、引数の数が2であることを確認しただけです。 2つの引数が有効なファイルであるかどうかは確認しませんでした。

5. 結論

この記事では、3つのmvコマンドを使用して2つのファイルのコンテンツを交換する方法を学びました。

さらに、この操作を便利に実行できるように関数を作成しました。