複数のファイルを含むディレクトリがありますfoo
。
.
└── foo
├── a.txt
└── b.txt
同じ名前のディレクトリに移動したい。
.
└── foo
└── foo
├── a.txt
└── b.txt
現在、一時ディレクトリを作成してbar
から移動し、foo
名前を次のようにbar
変更しています。bar
foo
mkdir bar
mv foo bar
mv bar foo
しかし、これは少し面倒な感じがし、bar
まだ使用されていない名前を選択する必要があります。
これを達成するためのよりエレガントで直接的な方法はありますか?それが重要な場合は、私はmacOSを使用しています。
答え1
名前がまだ使用されていない現在のディレクトリに一時ディレクトリを安全に作成するには、mktemp -d
次のように使用できます。
tmpdir=$(mktemp -d "$PWD"/tmp.XXXXXXXX) # using ./tmp.XXXXXXXX would work too
このmktemp -d
コマンドは指定されたパスにディレクトリを作成し、X
パス名の末尾に-esが任意の英数字に置き換えられます。作成したディレクトリのパス名を返し、その値を1tmpdir
に保存します。
tmpdir
その後、すでに行ったのと同じプロセスを実行するときは、その変数を使用して次にbar
置き換えることができます"$tmpdir"
。
mv foo "$tmpdir"
mv "$tmpdir" foo
unset tmpdir
最後に、unset tmpdir
変数を削除することです。
1 一般的にしなければならないTMPDIR
一時ファイルやディレクトリを作成するために使用したいディレクトリパスに環境変数を設定する機能がありますが、mktemp
macOSのユーティリティは他のBSDシステムの同じユーティリティとは少し異なる動作をするように見え、まったく異なる場所にディレクトリを作成します。 。しかし、上記はmacOSで有効です。使い方がややtmpdir=$(TMPDIR=$PWD mktemp -d)
簡単tmpdir=$(TMPDIR=. mktemp -d)
質問macOSでは、デフォルトの一時ディレクトリが別のパーティションにあり、そのfoo
ディレクトリに多くのデータが含まれている場合(つまり、速度が遅くなります)
答え2
macOSでは、rename
Homebrewインストールコマンド(Perlスクリプト)を使用できます。
brew install rename
-p
次に、(a la)を使用mkdir
して必要なディレクトリを作成し、-A
プレフィックスを追加します。
% mkdir -p foo/bar; touch foo/{a,b}.txt foo/bar/c.txt
% rename -p -A foo/ foo/*
% tree foo
foo
└── foo
├── a.txt
├── b.txt
└── bar
└── c.txt
名前を変更せずに変更を表示するには、実行します-n
(テストを実行):
% rename -p -A foo/ foo/* -n
'foo/a.txt' would be renamed to 'foo/foo/a.txt'
'foo/b.txt' would be renamed to 'foo/foo/b.txt'
'foo/bar' would be renamed to 'foo/foo/bar'
ビットファイルが存在する場合、simpleは*
そのファイルを選択できません。別の方法を使用してくださいrename
。
Bashはドットファイルを一致させるために
GLOBIGNORE
(間違って)使用します。*
$ GLOBIGNORE=.; rename -p -A foo/ foo/* -n 'foo/.baz' would be renamed to 'foo/foo/.baz' 'foo/a.txt' would be renamed to 'foo/foo/a.txt' 'foo/b.txt' would be renamed to 'foo/foo/b.txt' 'foo/bar' would be renamed to 'foo/foo/bar'
find
または、-print0
次のようrename
に使用されます-0
。% find foo -mindepth 1 -maxdepth 1 -print0 | rename -0 -p -A foo/ -n Reading filenames from STDIN Splitting on NUL bytes 'foo/b.txt' would be renamed to 'foo/foo/b.txt' 'foo/a.txt' would be renamed to 'foo/foo/a.txt' 'foo/bar' would be renamed to 'foo/foo/bar' 'foo/.baz' would be renamed to 'foo/foo/.baz'
答え3
コンテンツが最大パラメータ制限を超えるのに十分でない限り(そして「許容可能な」エラーメッセージを気にしない限り)、以下より複雑である必要はありません。
mkdir foo/foo
mv foo/* foo/foo
隠しファイルの処理に対する修正:
mkdir foo/foo
mv foo/{.,}* foo/foo
答え4
あなたはすでにそれを知っています。現在の日付/時刻(ナノ秒単位)やPIDを複合サフィックスとして含むターゲット名など、一時ディレクトリに別の名前を選択できますが、まだディレクトリが存在しないとします。
dir=foo # The directory we want to nest
now=$(date +'%s_%N') # Seconds and nanoseconds
mkdir "$dir.$now.$$" # Create a transient directory
mv -f "$dir" "$dir.$now.$$/" # Move our directory inside transient directory
mv -f "$dir.$now.$$" "$dir" # Rename the transient directory to the name with which we started
保証された強力なソリューションが必要な場合は、mkdir
成功するまで繰り返します。
now=$(date +'%s_%N')
while ! mkdir -m700 "$dir.$now.$$" 2>/dev/null
do
sleep 0.$$
now=$(date +'%s_%N')
done