`mv`で改行をファイル名に追加


11

それは深刻な問題です。私はいくつかのawkスクリプトをテストし、それらの名前に改行を含むファイルが必要です。


で改行をファイル名に追加することは可能mvですか?

私は今、これを行うことができますtouch

touch "foo
bar"

タッチで、コピーと貼り付けごとに改行文字を追加しました。しかし、私はfooReturnbar自分のシェルで書くことができません。

ファイル名に改行を含めるために、ファイルの名前を変更するにはどうすればよいですか?


2015/06/28を編集; 07:08 pm

zsh使用できる改行を追加するには、Alt+Return


2
なぜ聞くのですか?友達にジョークやトリックを作っていませんか?
Basile Starynkevitch、2015年

2
質問は削除しないでください。便利です。ただし、ファイル名の改行はできるだけ避けてください。
Basile Starynkevitch、2015年

2
でそれを行うことは、それを行うこととmv何が違うと思いますtouchか?同じことを試しましたか?
ケビン

2
さて、mvコマンドと同じくらい簡単にコピーしてコマンドに貼り付けることができますtouch
ケビン

2
したがって、OPをより明確に定式化することをお勧めします。特定のシェル環境では、echo "a [return] b"のように引用符で囲まれた文字列内に改行を入力できません。
2015年

回答:


22

(ファイル名に奇妙な文字を含めることは)悪い考えですが、あなたはそうすることができます

 mv somefile.txt "foo
 bar"

mv somefile.txt "$(printf "foo\nbar")"またはmv somefile.txt foo$'\n'bar、or なども実行できます。詳細はシェルに固有です。私はを使用していますzsh

詳細読むグロブ例えば、(7)グロブ。詳細はシェル固有の場合があります。しかし、それは理解/bin/mv を経て、(お使いのシェルによって)与えられているのexecve(2) 拡張された引数の配列:引数の拡張とグロブは、起動したシェルの責任です。

また、小さなCプログラムをコーディングして同じことを行うこともできます。

#include <stdio.h>
#include <stdlib.h>
int main() {
  if (rename ("somefile.txt", "foo\nbar")) {
     perror("rename somefile.txt");
     exit(EXIT_FAILURE);
  };
  return 0;
}

上記のプログラムをに保存しfoo.c、コンパイルしてgcc -Wall foo.c -o foo 実行します./foo

同様に、Perl、Ruby、Python、Ocamlなどで同様のスクリプトをコーディングできます。

しかし、それは悪い考えです。ファイル名の改行は避けてください(ユーザーを混乱させ、多くのスクリプトを壊す可能性があります)。

実際、 ファイルパスには、アクセント記号のない文字、数字、および+-/._% 文字(/ディレクトリの区切り文字)のみを使用することをお勧めします。「非表示」ファイル(で始まる.)は慎重に使用してください。ファイル名にスペースを使用するのは間違いだと思います。代わりにアンダースコア(例foo/bar_bee1.txt)またはマイナス(例foo/bar-bee1.txt)を使用してください


はい、わかっています。改行文字をコピーして貼り付けることができますが、コピーアンドペーストなしでそれを行うにはどうすればよいですか。
AB

4
ここにはコピーや貼り付けはありません。後に型付き改行がありますfoo
ダン・

ただし、コピーして貼り付けることもできます
kos

1
これは通常のファイルにとっては悪い考えですが、OPが述べたように、良いテストケースです。
artdanil 2015年

5
@そして,より無害であろう-(最初の位置のように)、または%。これらの推奨事項はすべて、主に一部のアプリケーションのバグ(OSの観点からは有効なファイル名に違反する)を回避するためのものです。バグを修正するのではなく、それらの文字を使用しないように人々に要求するのは後悔しています。
ステファンChazelas

19

bashを使用する場合、このコマンドは機能するはずです。

mv a $'b\nc'

4
で動作しますzsh)=も
AB

3
zshやFreeBSD shのようなbashは、ksh93からそれをコピーしました。
ステファンChazelas

どうもありがとうございました!-それは、それを使用して助言SO上で私自身の答えだった間、私は完全には、bashで$忘れstackoverflow.com/questions/1825552/grep-a-tab-in-unix/...
antimirov

6

私はあなたがmv解決策を求めたのを知っています、しかし警告にもかかわらず、これはrename(Perlパッケージで)簡単に行うことができます:

~/tmp$ touch foo
~/tmp$ rename 's/$/\nbar/' foo
Unsuccessful stat on filename containing newline at /usr/share/perl5/File/Rename.pm line 69.
~/tmp$ ls
foo?bar

、ありがとうございますrename。+1
AB

5

この問題の1つの側面は、本当のことではなくawk、シェルについてのほんの少しです。問題は、標準の標準ttyでは、ほとんどの場合、カーネルのtty規律が入力をバッファリングしている-それを画面にエコーし、それ以外の場所にはない-バックスペースなどを効率的に処理できるようにするためです。

ただし、Returnキーを押すか、改行を入力すると、バッファリングされたすべてのデータが読み取りアプリケーション(通常はシェル)に一度にプッシュされます。$PS2ぶら下がり引用符を入力した後、これを監視することでこれを観察できます。シェルが出力$PS2するのは、それが入力の一部のブロックを読み取っただけで、まだ完了していないためです。

したがって、便宜上、必要なのは\n、他のすべての入力をすぐにプッシュする必要なく、ewlineをターミナルバッファに送信する方法です。これを行うための標準的な方法は、キーシーケンスを使用することです。これにより、端末の次の入力文字CTRL+V引用されます。行いCTRL+V、その後CTRL+J-後者は文字通り入力する方法通常であるため、\newlineを。$PS2シェルがまだ入力を読み取っていないため、表示されていないときに機能することがわかります。

注しかしそのことは、ときない入力が以前のことを読んでCTRL+V、すべてのシェルには違いが行われていないだろう-ラインだけ規律のためにそれを引用していること。改行をシェルクォートして、それに意味のあることをしたいと思うでしょう。

ちなみに、CTRL+V他の方法でも便利に適用できます。たとえば"$(printf \\33)"ESC文字をシェルスクリプトに書き込む唯一の方法ではありません。また、最も単純な方法でもありません。この方法で最初にエスケープするだけであれば、入力ドライバーがキーボードを解釈せずに、キーボードが送信する任意の文字を文字どおりに入力できます。

シェルが何も完了しようとせずに、コマンドラインで<tab>を使用することがよくあります。補完を行うシェルは通常、<tab>をと同義stty eol \tに構成するため、補完システムを機能させるためにCTRL+V、慣れていない環境でも動作します。


2
「Ctrl + V」について言及していただきありがとうございます。私はそれについて答えを投稿しようとしていて、それからあなたの説明を見ました。
artdanil 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.