引数としてディレクトリを使用して1つのコマンドを実行し、同じディレクトリにcdする方法は?「そのようなファイルやディレクトリはありません」


15

以下を行うための短い関数を作成したいと思います。ファイル「file.tex」をドキュメントディレクトリに移動するとします。

mv file.tex ~/Documents

次に、cdそのディレクトリに移動します。

cd ~/Documents

これを任意のディレクトリに一般化し、これを実行できるようにします。

mv file.tex ~/Documents
follow

しているとfollow、コマンドが前のコマンドから先を読んで、それに応じて実行します。単純なディレクトリの場合、これはあまり時間を節約しませんが、ネストされたディレクトリで作業するとき、ただ使用できるとすればすごいでしょう

mv file.tex ~/Documents/folder1/subfolder1
follow

私はそれが比較的簡単だと思った、と私はこのような何かをすることができます

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

しかし、これはうまくいかないようです。echoした場合$place、目的の文字列を取得します(でテストしています~/Documents)が、最後のコマンドは

No such file or directory

ディレクトリは確かに存在します。私は迷っています。手伝ってくれませんか?


file.tex元の場所にとどまることを気にしない場合、シンボリックリンクは非常に優れた代替手段であることに注意してください。一度リンクするだけで、その後は常に最新バージョンを指します。
クロルタン

5
より簡単な方法:cd alt + .と入力して、前のコマンドの最後のトークンを置き換えます。繰り返して、最終トークンの履歴に戻ります。(最後のトークンとしてfoo &取得するため、トークンは引数ではありません&。)数値引数を使用できます(たとえば、escape-3 alt +。を使用)。
ピーター


回答:


18

関数を定義する代わりに、変数を使用できます。この変数$_は、前のコマンドの最後の引数に展開されbashます。使用する:

cd "$_"

mvコマンドの後。

履歴展開も使用できます。

cd !:$

関数を使用する必要がある場合:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

NB:この回答は、位置パラメータを扱っているときに使用した正確なコマンドライン引数形式を対象としています。他の形式、例えばmv -t foo bar.txt、事前に特定のチェックを組み込む必要がある場合、ラッパーが適切です。


履歴展開(cd!:$)は完全に機能します。ありがとうございました。ただし、もう一方(cd "$ _")はそうではありません:mv file.tex〜/ Downloads / cd "$ _" bash:cd:__bp_preexec_invoke_exec:そのようなファイルやディレクトリはありません。ありがとうございました。
火災

私は常に(やや無駄に)cd !$またはを入力しましたcd $(dirname !$)$_変数について知らなかった!
カルビンリー

mv -t ~/Documents file.texでは、代わりに行うとmv file.tex ~/Documentsどうなりますか?結論として、これが一般的なケースで解決できるかどうかはわかりません...ラッパー関数の周りまたはその再実装mvが良いかもしれません...
CVn

@MichaelKjörling単純に動作しません。この例は、OP(エッジ)(またはすべての)ケースではなく、OPのケースをカバーするためのものです
。– heemayl

コロンは必要ありません。!$入力と同等!:$で高速です。
ワイルドカード

14

標準のbashキーバインドでは、この組み合わせAlt.により、前のコマンドラインの最後の引数が現在の引数にコピーされます。だから、タイピング

$ mv foo ~/some/long/path/
$ cd <Alt><.>

もたらすだろう

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

そして、単語よりもさらにタイピングが少なくなりますfollow

利便性を高めるために、Alt.組み合わせを繰り返すと、以前のすべてのコマンドラインの最後の引数を参照します。

補遺:このキーの組み合わせに対応するbashコマンド名はyank-last-argまたはinsert-last-argumentです。これは、「履歴を操作するコマンド」の下のbashのマンページ、またはより網羅的なBashリファレンスマニュアルにあります。


1
それは賢いです。ありがとう!私はこれが存在することを知りませんでした。
火災

@Fireこれらのコマンドのリファレンスを追加したので、もっと興味深いキーバインディングを見つけることができます(そして、いつものように、すぐに忘れてしまいます)。
ドゥブ

1
<esc>それ.から、と同じ結果を得るために使用することもでき<alt>+.ます。これは、エスケープするためにcapslockを再マップしたときに便利です:)
gnur

1
@gnur vi(m)ユーザー、と思います。;-)
ドゥブ

6

ほぼ確実に、パラメーター展開の前にチルダ展開が発生するという問題に直面しています。これは簡潔な例で説明できます。

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

これはで対処できますeval。とにかく、eval履歴からコマンドを取得しており、次のような任意の展開を含めることができるため、が必要になります。

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(これらの値の再展開が、発生した元の展開と一致しなくなる可能性があるなどの問題がありcompute_folder_nameます。いくつかのグローバル変数をインクリメントする関数だとします。)


4
必要ありませんeval。(Ever。)しかし、展開シーケンスの問題については十分に確認してください。evalここでの使用に対する履歴拡張のより大きな推奨性について言及する場合、これは私の意見では最良の答えになります。他のどれも、元のポスターのソリューションが機能しなかった理由を実際に説明していません。
ワイルドカード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.