上書きされたファイルの新しい名前を生成して上書きを防止しますか?


8

同じ名前の既存のファイルがある場合、ファイルに新しい名前を生成するにはどうすればよいですか?デスクトップ環境では、ファイル名の最後に番号を追加して新しい名前を生成しますが、これはコマンドラインからどのように実行できますか?

BusyboxでAndroidオペレーティングシステムを使用しています。


1
Qを拡張して、Androidに関してこれらのファイルを作成する容量を指定できますか?Java?どんなツールがありますか、busybox?または単にバニラアンドロイド?
slm

@user slmタブレットのダウンロードフォルダーに含まれるファイルをバックアップするために使用します。プログラムは拡張子に基づいてファイルをそれぞれのフォルダーにソートします。これを行うpythonスクリプトを作成しましたが、プログラムは遅く、同じ名前のファイルは上書きされます。私はプログラムをbashに書き直している最中です。新しい名前の生成は、私が苦労していた部分です。
kyle k 2013

お返事ありがとうございます!のバージョンにアクセスできますmktempか?
slm

@user slm busyboxがインストールされていて、含まれていますが、プログラムからシステムコールを実行するmktempと機能しません。
kyle k

何らかのエラーで動作しませんか?また、このシステムコールはどこから発信していますか?Python?
slm

回答:


5

あなたがPOSIXシェルを持っていると仮定すると、これを行うことができます:

mv() {
        eval "DEST=\${$#}" #The destination is the last positional parameter
        if [ -e "$DEST" ] && ! [ -d "$DEST" ];then
                PREFIX=${DEST%.*}
                COUNT=1
                EXT=${DEST##*.}
                args= i=1
                while [ $i -lt $# ]; do args="$args \"\${$i}\"" i=$((i+1)); done
                DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                while [ -e "$DEST" ];do
                    COUNT=$((COUNT+1))
                    DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                done
                eval "command mv $args \"\$DEST\""
        else
                command mv "$@"
        fi
}

これの使い方

これは関数なので~/.bashrc、通常のように保存して呼び出しますmv

これは何をしますか

  • 元のmv実行可能ファイルへのパスをMV変数に格納します
  • 呼び出された最後の引数を変数に取得します DEST
  • DEST存在し、ディレクトリではない場合、この関数は、名前変更がファイルを破壊しようとしていると想定します
  • 次に、最終的な名前のプレフィックス(.拡張をマークするfinalの前のすべて)、拡張(最終的なの後の.すべて)、カウント(存在する場合、最終的なの後のプレフィックス内の何か)を抽出し-ます。
  • カウントが見つからなかった場合、抽出されたカウントはゼロに設定され、前のステップで見つかったカウントに設定されます。
  • 現在のカウントが増加します
  • 次に、関数は、元のすべての引数(スイッチ+ファイル名)から最後の引数を差し引いてそれ自体を呼び出し、元の呼び出しの最後の引数の代わりに新しいファイル名を追加します。新しい名前は古い名前ですが、拡張子の前に3桁のカウンター(ゼロ詰め)が追加されています。
  • この関数は再帰的です。なぜなら、あなたが言っmv a.txt b.txtていた場合、最初に試すからmv a.txt b-001.txtです。次のmv呼び出しも関数自体である必要b-001.txtがあります。存在する場合は、存在しない新しいファイル名が見つかるまでカウンターを増分し続けたいからです。
  • 最後の引数が存在しないかディレクトリの場合、元のmv実行可能ファイルが元の引数で呼び出されます。

注意事項

  • 既存のファイルを繰り返し上書きできる回数は、カウンターの長さによって異なります(この場合は999回)。ファイルシステムのiノード制限を含む桁数を選択して、ファイルを作成できる限りこれが機能することを確認できます。
  • に似た名前のファイルを上書きしようとすると、そのファイルfoo-001.txtはに移動されfoo-001-001.txtます。

ノート

  • 命名パターンを変更するに3は、printfステートメントのin を好きなように変更します。
  • このコードはテスト済みです
  • これは非常に単純化されており、惨めに失敗するエッジケースがあると確信しています。あなたが何か見つけたら、私はあなたのためにそれらを試して修正することがうれしいです。それまでは、本番マシンでこれを試さないでください。

ここに同じ心:P
Rahul Patil

@RahulPatil GUIの動作を複製しようとしているのを除いて。
ジョセフR.

それは素晴らしい、私はまだGUIを使用していません。
Rahul Patil 2013

存在する場合、宛先ファイルを上書きします。paste.ubuntu.com/ 6071897
Rahul Patil

@RahulPatilあなたが何を言っているのかわからない:あなたの例では、それ/tmpは存在するディレクトリであることを識別し、/bin/mv file1 /tmp私は問題がどこにあるのかわからないので電話しました。
ジョセフR.

3

私は通常、このツールmktempを使用して信頼できる一時ファイルを作成します。デフォルトではファイルを作成しますが、-dスイッチを使用してディレクトリを作成することもできます。

現在のディレクトリのファイルに一時的な名前を作成する方法は次のとおりです。

$ mktemp somefile.XXXXX
somefile.kiDad

$ mktemp somefile.XXXX
somefile.MrSW

$ mktemp someotherfile.XXXXXXXXXXX
someotherfile.Um4aXKrt3lv

これにより、ファイルが作成されます。

参考文献


2
mktempAndroidではできませんが、とにかく私から+1してください。これは、U&Lの賢明な質問に対するよい回答です。
goldilocks 2013

@goldilocks-親切な言葉をありがとう いつもいいね!
slm

@goldilocks-busyboxが含まれている場合、すぐに知っていますか?その中にmktempの実装があります。Androidについてはあまり知りません。code.google.com/p/abb/source/browse/mktemp.c?name=upstream/...
SLM

1
Androidのbusyboxはデバイスがルート化されている(脱獄されている)必要があるようです。ネイティブシェルがある/system/bin/shとのようですsh互換性-などの構造if [ -w $file ]の仕事、mvそしてrename利用可能です-ちょうど組み込みコマンドでこれを行うためのスクリプトが動作するはずですので。
goldilocks 2013

@goldilocks-チェックしてくれてありがとう。これを見つけるために何を探していますか?Androidで足を濡らしたいのですが、電話やデバイスを持ちたくありません。
slm

2

ここに、警告のないジョセフRのスクリプトの代替案があります。数値のサフィックスをパス名(パスはディレクトリまたはファイルの場合もあります)に追加し、まだ存在しないサフィックスが見つかるまでサフィックス値を増やします。などのその他のユーティリティlogrotateは同様のパターンを使用しますが、既存のすべてのコピーをローテーションして、新しいもののサフィックスが常に「0」になるようにします。その意味ではこれはローテーションではないので、これを呼び出しますdotmv。それfile.0最も古いコピーになることを覚えておいてください。

例えば:

dotmv somefile.txt

の名前を変更します。somefile.txt somefile.txt.0後者が存在しない場合はsomefile.txt.1、そのようになります。複数のファイル(dotmv this that "the other thing"など)をリストすることができ、それらはすべてドット移動されます。

これはPOSIXに準拠していると思いますset -o posix-bash上で実行されます(ただし、これは疑わしいテストです)。私はandroid(jelly bean 4.2.1)シェルでもテストしましたが、そこで動作します。ただし、Androidでは、指示どおりにシバンを変更または実行するsh dotmv必要があります。ルート化されたデバイスがない限り、とにかくスクリプトを実行可能にする方法がないためです。シバンを変更すると、使用できるようになりますexec dotmv

#!/bin/sh
# On android change that to /system/bin/sh.

# Validate arguments
if [ $# -lt 1 ]; then
    echo "A list of one or more paths is required."
    exit 1
fi

# Checks if a path exists and can be moved.
checkPath () {
    if [ ! -e "$1" ]; then
        echo "'$1' does not exist."
        return 1;
    fi
    if [ ! -w "$1" ]; then
        echo "Cannot move '$1', permission denied."
        return 1;
    fi
    return 0;
}

# Finds a new path with numerical suffix.
getName () {
    suf=0;
    while [ -e "$1.$suf" ]
        do let suf+=1
    done
    Dest=$1.$suf
}

# Loop through arguments -- use quotes to allow spaces in paths.
while (($#)); do
    Src=$1
    Dest=$1
    shift
    checkPath "$Src"
    if [ $? -eq 0 ]; then
        getName "$Src"
        mv "$Src" "$Dest"
    fi
done

うまくいけば、ここでのロジックは非常に簡単です。これは、Python、C、またはファイルI / Oを備えたその他の完全な手続き型言語で実装できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.