フォルダー名がこのようになったのはなぜですか。スクリプトを使用してこれを修正するにはどうすればよいですか?


15

他の場所に答えがある場合は申し訳ありませんが、問題を検索する方法がわかりません。

Redhat Linux HPCサーバーでいくつかのシミュレーションを実行していましたが、フォルダー構造を処理して出力を保存するためのコードには不幸なバグがありました。フォルダーを作成するための私のmatlabコードは次のとおりです。

folder = [sp.saveLocation, 'run_', sp.run_number, '/'];

どこsp.run_numberが整数でした。文字列に変換するのを忘れていましたが、何らかの理由でmkdir(folder);(matlabで)実行は成功しました。実際、シミュレーションは問題なく実行され、データは一致するディレクトリに保存されました。

今、フォルダ構造がクエリ/印刷されると、次の状況が発生します:

  • タブのオートコンプリートを試みると: run_ run_^A/ run_^B/ run_^C/ run_^D/ run_^E/ run_^F/ run_^G/ run_^H/ run_^I/
  • 私が使うときlsrun_ run_? run_? run_? run_? run_? run_? run_? run_? run_? run_?
  • 私はrsyncを使ってどこでもMy Macに転送する場合--progress:オプションショーrun_\#003/で整数を一致数(私は仮定)となどをsp.run_number10日の実行があるので、3桁にパッド入りrun_\#010/
  • ファインダーでフォルダーを表示すると、 run_ run_ run_ run_ run_ run_ run_ run_ run_ run_?
  • この質問を見て、ls | LC_ALL=C sed -n l私が得るコマンドを使用します:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$

cdこれらの表現のいずれかを使用してフォルダーに管理することはできません。

これらのフォルダーは何千もあるので、スクリプトでこれを修正する必要があります。これらのオプションのどれがフォルダの正しい表現ですか?これらのフォルダーをプログラムで参照して、bashスクリプトを使用して適切にフォーマットされた名前に名前を変更するにはどうすればよいですか?好奇心のために、そもそもこれは一体どうやって起こったのでしょうか?


4
「タブでオートコンプリートしようとすると:...入力しようとすると...」なぜオートコンプリートを完了させないのですか?また、^A文字どおりに^続きAますが、Ctrl-A(Ctrl-Aは一般にシェルのショートカットであるため、Ctrl-V Ctrl-Aを使用して入力できます)。
ムール

いない作業を行い@muru ...私は限り取得run_し、私が何かを入力する必要があります
フィル

申し訳ありませんが、私はCD経由で私を取得するために管理し、あなたの編集を、見て前にコメントした
フィル


9
ところで、matlabのmkdirがこれを行った「何らかの理由」は、UNIXファイルシステム上のファイルまたはディレクトリ名の無効な文字のみがNULおよびスラッシュであるため/です。制御文字を含む他の文字はすべて有効です。sp.run_numberが0の場合、matlabが何をしたのかわかりません(おそらくrun_、NULバイトがディレクトリ名文字列を終了させるため、エラーで中止するか、生成します)。もちろん、これは、NULバイトが含まれる16ビット(またはそれ以上)の値に対しても問題があり、matlabを実行しているシステムのエンディアンによっても異なります。
cas

回答:


26

perl renameユーティリティ(prenameまたはfile-rename)を使用して、ディレクトリの名前を変更できます。

注:これはrenamefrom util-linuxや他のバージョンと混同しないでください。

rename -n 's/([[:cntrl:]])/ord($1)/eg' run_*/

これは、perlのord()関数を使用して、ファイル名の各制御文字をその文字の序数に置き換えます。たとえば^A、1に^Bなり、2になります。

-nオプションが何を示すために、ドライ・ランのためにあるrename でしょう、あなたがそれを許可すれば行います。-v実際に名前を変更するには、削除(または冗長出力の場合は置き換え)します。

操作のe修飾子s/LHS/RHS/egにより、perlはRHS(置換)をperlコードとして実行$1します。これは、LHSからの一致データ(制御文字)です。

ファイル名にゼロが埋め込まれた数字が必要な場合は、ord()と組み合わせることができますsprintf()。例えば

$ rename -n 's/([[:cntrl:]])/sprintf("%02i",ord($1))/eg' run_*/ | sed -n l
rename(run_\001, run_01)$
rename(run_\002, run_02)$
rename(run_\003, run_03)$
rename(run_\004, run_04)$
rename(run_\005, run_05)$
rename(run_\006, run_06)$
rename(run_\a, run_07)$
rename(run_\b, run_08)$
rename(run_\t, run_09)$

上記の例は、matlabスクリプトで0〜26の範囲内にある場合 sp.run_numberのみ機能します(したがって、ディレクトリ名に制御文字が生成されます)。

任意の1バイト文字(つまり、0..255から)を処理するには、次を使用します。

rename -n 's/run_(.)/sprintf("run_%03i",ord($1))/e' run_*/

sp.run_number255以上の場合は、unpack()代わりにperlの関数を使用する必要がありますord()。matlabが文字列で未変換のintをどのように出力するか正確にはわかりませんので、実験する必要があります。詳細perldoc -f unpackをご覧ください。

たとえば、次のコードは8ビットと16ビットの両方の符号なしの値をアンパックし、それらを5桁の幅にゼロで埋め込みます。

 rename -n 's/run_(.*)/sprintf("run_%05i",unpack("SC",$1))/e' run_*/

詳細をありがとう!私はそれをテストしようとしている-nオプションが、それは私にその無効なオプションを語っています-バージョン情報は私を与えるrename from util-linux 2.23.2のでI'mnot必ずその同じ機能
フィル

3
そのため、ユーティリティのperlバージョンを指定しましたrenameutil-linuxさんはrenameはるかに少ない可能、非常に異なっており、コマンドラインオプションは互換性がありません。debianなどを実行している場合は、file-renameパッケージをインストールしてみてください。それ以外の場合は、ディストリビューションに適切なパッケージをインストールしてください。すでにインストールされている可能性があります。実行するprenamefile-rename、単にの代わりに試してくださいrename
cas

うん、そうだと思った。それらのいずれかを動作させることができるかどうかを確認します。時間を割いて私を助けてくれてありがとう!
フィル

11

好奇心のために、そもそもこれは一体どうやって起こったのでしょうか?

folder = [sp.saveLocation, 'run_', sp.run_number, '/'];

どこsp.run_numberが整数でした。文字列に変換するのを忘れましたが、何らかの理由で実行していmkdir(folder)ます。(matlabで)まだ成功しています。

そのため、mkdir([...])Matlabでは配列のメンバーを連結して、ファイル名を文字列として作成するように見えます。しかし、代わりに数字を付けたので、数字はコンピューター上のキャラクターの本当の姿です。だから、ときsp.run_numberだった1、それはあなたの価値を持つ文字与え1、その後、値を持つ文字2などを、

これらは制御文字であり、印刷可能な記号はありません。端末で印刷すると、他の結果が生じます。その代わり、それらはしばしば異なる種類のエスケープで表されます:\001(8進数)、\x01(16進数)は、^Avalueを持つ文字の一般的な表現です1。値がゼロの文字は少し異なります。CおよびUnixシステムコールで文字列の末尾をマークするために使用されるのはNULバイトです。

31を超えると、印刷可能な文字が表示されるようになります。32はスペースですが(あまり見えません)、33 = !、34 = "などです。

そう、

  • run_ run_^A/ run_^B/—最初run_の文字はゼロバイトの文字に対応し、文字列はそこで終了します。他の例は、シェルがを使用して制御コードを表示することを好むことを示しています^A。表記は、数値1のcharをとして入力できることを示唆してCtrl-Aいますが、シェルに、制御文字としてではなく、リテラルとして解釈するように指示する必要がありますがCtrl-V Ctrl-A、少なくともBash ではそうする必要があります。

  • ls:run_ run_? run_?lsターミナルで印刷できない文字を印刷するのを好まず、疑問符に置き換えます。

  • rsync:run_\#003/—私にとっては新しいことですが、考え方は同じです。バックスラッシュはエスケープを示し、残りは文字の数値です。ここの数字は、より一般的なのように、8進数であるように思え\003ます。

  • コマンドを使用してls | LC_ALL=C sed -n l... run_\006$ run_\a$ run_\b$ run_\t$- \a\b及び\tCは、それぞれ、アラーム(ベル)、バックスペースやタブのエスケープされています。これらの数値は7、8、9であるため、なぜ後に続くのかが明確になり\006ます。これらのCエスケープを使用することは、制御文字をマークするもう1つの方法です。末尾のドル記号は、行の終わりを示します。

cd私の仮定を仮定することは正しいです、cd run_奇数末尾の文字なくても、その1つのディレクトリに移動しなければならない、とcd run_?疑問符は任意の1文字に一致グロブ文字であるため、エラーを与えるべきである、と複数の一致のファイル名がありますが、cd唯一の期待しています。

これらのオプションのどれがフォルダの正しい表現ですか?

ある意味でそれらのすべて...

Bashでは、引用符内の\000and \x00エスケープ を使用し$'...'て特殊文字を表すことができるため、$'run_\033(8進数)または$'run_\x1b'文字値27(たまたまESC)のディレクトリに対応します。(Bashは10進数のエスケープをサポートしているとは思わない。)

casの答えには、それらの名前を変更するスクリプトがあるので、ここには行きません。


GNUの場合ls、非印刷文字の表示方法を制御するために、-b/ --escapeおよび--quoting-style=、またはQUOTING_STYLE環境変数を含むいくつかの引用オプションがあります。ただし、文字バージョンよりも8進エスケープを優先させるオプションはないと思います。
トビー・スペイト

3

最も簡単なのは、事故が発生したのと同じ環境で間違ったファイル名と正しいファイル名を作成し、フォルダーを正しい名前に移動/名前変更することです。

既存の名前間の衝突を避けるために、別の宛先フォルダーを使用することをお勧めします。

./saveLocationA/wrongname1 -> ./saveLocationB/correctname1
./saveLocationA/wrongname2 -> ./saveLocationB/correctname2
./saveLocationA/wrongname3 -> ./saveLocationB/correctname3

可能であれば、スクリプトを修正して再度実行することをお勧めします。奇妙なバグの事後分析を修正すると、おそらくより多くのコストがかかり、新しい問題が発生する可能性があります。

幸運を!

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