

Ubuntuの標準のbashシェルで､たとえば長いファイル名のファイルのバックアップを  
手でコマンド入力するときに､何か省略して簡単に打ち込める方法は無いでしょうか?

例

[code]

    cp very-long-filename.txt very-long-filename.txt.old
    
[/code]

を

[code]

    cp (very-log-filename.txt) \1.old
    
[/code]

のように前方参照させるようなやりかたです


CC BY-SA 3.0
2015-10-19T08:17:56.130
17812
2015-11-06T11:59:52.833
2015-10-19T12:15:52.383
7290
12849
question
bash ubuntu
Ubuntuのbashで`cp 文字数が多いファイル名 文字数が多いファイル名.old`を簡単に打つ


Bash の対話セッションなら Emacs や vi
のキーバインディングでコマンドラインの編集ができますので、このような例ですと私は頭を使う前に次のように操作しがちです。

まず次のようにタイプしてから、

[code]

    $ cp very-long-file-name.txt
    
[/code]

このように操作します。

  * `Ctrl`+`A` (先頭に移動)
  * `Ctrl`+`F`
  * `Ctrl`+`F` (カーソルが `cp` の後にくる)
  * `Ctrl`+`K` (行末までのテキストをキルバッファに格納)
  * `Ctrl`+`Y` (キルバッファをヤンク)
  * `Ctrl`+`Y` (もういちどヤンク)
  * `.``O``L``D` (`.old` を追加)
  * `Ctrl`+`M` (実行)

日本語が混じっていたりなど、面倒なファイル名を扱う場合には特に便利です。


CC BY-SA 3.0
2015-10-19T09:10:14.073
17814
2015-10-19T09:15:56.107
2015-10-19T09:15:56.107
9873
9873
17812
answer


[bash](/questions/tagged/bash "'bash' のタグが付いた質問を表示") の対話セッションなら [tab]
キーでファイル名補完ができるので  
cp や mv など、既にあるファイル名を渡す目的には適当に補完しながら打ち込むのが簡単。  
この例では末尾補填なので、２回同じファイル名を補完で入力し、  
最後 [backspace] でスペースを消して .txt の直後にカーソルを持ってきて .old とか。

Emacs に慣れている人（オイラを含む）なら yaegashi さんの Emacs-bind のほうが楽っすけど  
オイラの周囲の人間を見てる範囲では、慣れてない人でも [tab] 補完は違和感なくできる様子です。


CC BY-SA 3.0
2015-10-19T10:00:33.490
17816
2015-10-19T10:00:33.490
8589
17812
answer


いろいろやり方はあると思いますが、私がよくやるのは次の2パターンです。

まず、ここまで入力するのは共通。カーソル位置は右端にあるものとします。

$ cp very-long-file-name.txt

パターン1:

  1. Ctrl+`w` を入力。(`very-long-file-name.txt` をカット）
  2. Ctrl+`y` を入力。(`very-long-file-name.txt` をペースト)
  3. `` を入力。(スペースを入力)
  4. Ctrl+`y` を入力。(`very-long-file-name.txt` をペースト)
  5. `.old` を入力して Enter して実行。

パターン2:

  1. Enter を押して実行。(このパターンだと引数が足らずエラーになるが気にしない)
  2. Ctrl+`p` を入力。 (エラーになった前回のコマンドラインをヒストリーから復帰)
  3. `` を入力。(スペースを入力)
  4. ESC,`.` を入力。(ESC キー、ドット `.` を順番に押す。前回のコマンドラインの最後の引数をペースト)
  5. `.old` を入力して Enter で実行。

といった感じです。ご参考まで。


CC BY-SA 3.0
2015-10-19T12:11:15.087
17823
2015-10-19T12:11:15.087
3061
17812
answer


for文でやる方法もあります。

[code]

    for f in very-long-filename.txt; do cp $f $f.old; done
    
[/code]


CC BY-SA 3.0
2015-10-20T03:59:44.900
17837
2015-10-20T04:17:35.353
2015-10-20T04:17:35.353
12865
12865
17812
answer


GNU cp 限定ですが

[code]

    $ cp -bf -S .old file file
    $ ls
    file  file.old
    
[/code]

環境変数 `SIMPLE_BACKUP_SUFFIX` に `.old` を設定すれば `-S .old` を省略できます。

[code]

    $ export SIMPLE_BACKUP_SUFFIX=.old
    $ cp -bf file file
    $ ls
    file  file.old
    
[/code]

個人的には `.old` 付けるより バックアップの上書きを回避するため 番号を付けるほうがいいと思います。

[code]

    $ cp --backup=t -f file file    ←1回目
    $ cp --backup=t -f file file    ←2回目
    
[/code]

もしくは

[code]

    $ export SIMPLE_BACKUP_SUFFIX=numbered
    $ cp -bf file file    ←1回目
    $ cp -bf file file    ←2回目
    
[/code]

結果は

[code]

    $ ls
    file  file.~1~  file.~2~
    
[/code]

なお `mv` `ln` `install` `patch` でも同じオプションが使えます。


CC BY-SA 3.0
2015-10-22T03:34:58.240
17925
2015-10-22T03:34:58.240
5008
17812
answer


何故か `bash` の履歴展開機能を挙げている人がいないので書いておきます。履歴展開 (history expansion;
対話シェルで既定で有効になっています) の指定を使えば、まさに質問文の様な事ができます。即ち、

例

[code]

    cp very-long-filename.txt very-long-filename.txt.old
    
[/code]

を

[code]

    cp very-log-filename.txt !#:1.old
    
[/code]

と書く事ができます。`!#:1` の部分が履歴展開の指定です。意味は「`!` (= 履歴展開) `#` (= 現在のコマンドライン) `:` (= の )
`1` (= 1つ目の単語)」です。上記を実行すると、コマンド内容が一旦 `cp very-long-filename.txt very-long-
filename.txt.old` に展開されてから実行されます。

履歴展開の指定方法の詳細については [`man
bash`](http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbCX)
を御覧になるのが良いと思います。履歴展開は指定ミスをしやすいので、慣れない内は直接実行せずに一旦コマンド `M-^` (history-expand-
line) を用いて展開してから実行するのがおすすめです。履歴展開の指定 `!～` をコマンドラインに入力してから `M-^`
を押すと、コマンドラインの内容が履歴展開後の内容に置き換わります。


CC BY-SA 3.0
2015-11-06T11:59:52.833
18481
2015-11-06T11:59:52.833
5300
17812
answer