ファイル名のスペースが嫌い


61

それは単純だ。ファイルの命名時に人々がスペースを使用するとき、私は我慢できません。それは時々コンソールコマンドを破壊し、lsの出力をくします。

課題は、プログラム(ASCII文字のみ)を記述することです。

  1. 現在のディレクトリ内のすべてのファイル(ディレクトリを含む)の名前を、スペースが削除または '_'に置き換えられたバージョンに変更します
  2. 衝突時には、一意の識別子を追加する必要があります(あなたまで)
  3. すべてのサブディレクトリに再帰的に下降します

UNIXスタイルのパス名を想定できます。とにかくWindowsマシンでこのプログラムが必要なのは誰ですか?

これはコードゴルフで、最短のプログラムが勝ちます(#ascii文字)。私はスペースがとても嫌いなので、各スペースを2回カウントする必要があります。

言語、スコア、プログラム、および実行方法の簡単な説明を入力してください。

プログラムは、Linuxマシン上で合理的な努力でコンパイルおよび実行する必要があります。

編集:Etanがテスト用のファイル構造を要求したので、適切なファイルツリーを作成するために現在使用しているスクリプトを次に示します。

#!/bin/bash
rm -r TestDir

touchfiles()
{
    touch my_file
    touch my__file
    touch "my file"
    touch "my  file"
    touch " my_file  "
}

mkdir TestDir
cd TestDir

touchfiles

for dir in "Test Sub" Test_Sub "Te stSub" Te_stSub
do
    mkdir "$dir"
    cd "$dir"
    touchfiles
    cd ..
done

22
これは、ASCII文字を使用せずに作成されたソリューションを求めています。
デニスジャエルディン14

50
今私はホワイトスペースを学びたいです
ブルーノ14

10
@BrunoJがホワイトスペースでこれを行うには、まずWSでファイルアクセスシステムを開発する必要があります。それは実際の挑戦よりも挑戦的だと思います。
Nzall 14

7
誰かがC / C ++ソリューションを投稿するのを待って、それを盗み、コンパイルし、ゼロスペースのx86マシンコードとして16進数で投稿できるようにします![または多分base64]
マークKコーワン14

10
ファイル名にアンダースコアが嫌いです。ダッシュを使用します。
レブム博士14

回答:


10

Zsh + GNU coreutils — 48バイト(1スペース)

for x   (**/*(Dod))mv   -T  --b=t   $x  $x:h/${${x:t}// }

(ASCII)スペースが嫌いなのに、タブや改行は問題ないのは奇妙ですが、すべての種類が必要だと思います。

zmvは解決したファイルの名前変更の問題の多くを簡潔に(そして少しだけ目立た)。ただし、ターゲットは一意であることを主張します。一意のサフィックスを簡単に追加できますが、必要な場合にのみサフィックスを追加するには、すべての作業をやり直す必要があります。したがって、代わりに手動でループし、衝突の場合にGNU mvに依存して一意の識別子を追加します(--backupオプション、および--no-target-directoryターゲットが既存のディレクトリである場合、そうでなければmvソースをそのディレクトリ内に移動します)。

(od)は、コンテンツの後に表示されるディレクトリ(findのような)で出力をソートするためのglob修飾子-depthです。Dglobにドットファイルを含めます。:hおよび:tは、と同様の履歴修飾子です。dirnamebasename

mvglobにはスペースのないファイル名が含まれているため、ファイルの名前を自分自身に変更するように呼び出されていると文句を言います。C'est la vie。

ゴルフされていないバージョン:

for x in **/*\ *(Dod); do
  mv --no-target-directory --backup=numbered $x ${x:h}/${${x:t}// /}
done

1
これは私のファイルの名前を変更しません!
M.ヘルツカンプ14

@ M.Herzkampああ、そうです、zmv前に爆弾を投げるとmv衝突を整理する機会があります。わかりました、私はこれを手動でやっています。ドットファイルをスキップすると同じ長さになり、そうしないと文字を保存することさえできます。
ジル 'SO-悪であるのをやめる' 14

1
今では機能しています。ところで:私はスペースに対して本当にtheみを持っていたときにスペースペナルティを含めました;)皮肉なことに、チャレンジを投稿したときにスペースを除外しませんでした:P
M.Herzkamp 14

13

Bash 116バイト、16スペース

find . -depth -exec bash -c 'B=${0##*/}
M="${0%/*}/${B// /_}"
while [ -e "$M" ]
do M=$M.
done
mv "$0" "$M"' {} \;

エラーを抑制して、さらに2バイトを増やしたわけではありません。これには衝突はありません。

POSIX以外のGNU findが予想される場合、これをさらに短縮できます。

Bash 110バイト、15スペース

find -d -exec bash -c 'B=${0##*/}
M="${0%/*}/${B// /_}"
while [ -e "$M" ]
do M=$M.
done
mv "$0" "$M"' {} \;

スペースを置き換える代わりに削除すると、2バイト少なくなります。

Bash 108バイト、15スペース

find -d -exec bash -c 'B=${0##*/}
M="${0%/*}/${B// }"
while [ -e "$M" ]
do M=$M.
done
mv "$0" "$M"' {} \;

注:スペースの代わりにタブを使用できる場合、必要なスペースは1つだけです(2行目の置換の一致ルール内のスペース)。

二重引用符でバグを発見してくれた(そしてソリューションを提供してくれた)Dennisに感謝


11
余分なスペースは、私をモックするためにそこにありますか?;-)
M.Herzkamp 14

@ M.Herzkampコピーアンドペーストのエラーでしたが、実際にはそこにあります。さらに2ポイント獲得したと思います。また、-depthGNU では、に置き換えることができます-dが、非推奨であると文句を言います。ゴルフのルールがわからないのですが、できますか?
pqnet 14

2
動作する限り、許可します。ただし、将来のバージョンで廃止が廃止になった場合は、この答えに戻って、正しくないためにそれをダウン投票する必要があります
;

2
ファイル名に二重引用符が含まれている場合、これは正しく機能しません。これを修正するbash -c 'B=${0##*/}...' {} \;には、代わりに実際に短いものを使用できます。
デニス

3
私は私がその男になると思いますが、N変数はどうなっていますか?それは...定義されることはありません
スティーヴン・ペニー

9

Python 180バイト

from    os  import*
t,c,h='.',chdir,path
def g(p):
    c(p)
    for x   in  listdir(t):
        if h.isdir(x):g(x)
        n=x.replace(' ','')
        while h.exists(n):n+=t
        if' 'in x:rename(x,n)
    c(t*2)
g(t)

インデントにタブを使用する場合、スペースは2つだけです:-)


他のほとんどの答えも、スペースの代わりにタブを使用することでスコアを改善できると思います。
カスペルド

しかし、あなたの提出はスペースを使用しませんか?(作業コードの+1)
M.Herzkamp 14

答えにタブ文字を付ける方法がわかりません...
エマヌエーレパオリーニ14

2
タブに置き換え:-)
エマヌエーレパオリーニ


5

衝突するファイルのサフィックスの順序が既存のファイルに先例を与える必要がない場合、次のように機能します。

bash / find / mv 84バイト、16スペース

find -depth -execdir bash -c '[ "${0//[^ ]}" ] && mv -{T,--b=t} "$0" "${0// }"' {} \;

bash / find / mv 82バイト、14スペース

find -depth -execdir bash -c '[ "${0//[^ ]}" ]&&mv -{T,-b=t} "$0" "${0// }"' {} \;

&&2バイトのスペースを節約するために寄り添います。

bash / find / mv 60バイト、11スペース

find -d -execdir bash -c 'mv -{T,-b=t} "$0" "${0// }"' {} \;

エラー保護を解除して、最初にスペースがないファイルのmvからエラーを取得します。

編集:{}デニスが思い出したようにから引用を削除しました。また、ファイルをそれ自体の上に移動することについて既に叫んfindでいる最短バージョンでmvは、移植性と非推奨について叫ぶことができます。

編集2:追加-Tするmv代わりにpqnetで指摘したように名前を変更するの入れ子のディレクトリを避けるためにコマンド。1つのスペースを使用するだけで1文字のコストでブレース拡張を使用しました。


-d代わりに使用でき-depth、引用符は必要ありません{}
デニス14

@デニスうん。-dpqnetの答えで会話を見ましたが、mv悲鳴を黙らせていたので、悲鳴を避けたいと思いましたfind。私はおそらく叫び声のためにそれを短くする必要がありますが。そして、ええ、私はあなたがこの場合に必要がないこと{}知っているにもかかわらず、何らかの理由でいつも引用しています。習慣の力だと思います。
エタンReisner 14

1
ディレクトリ名で衝突が発生すると、スペースが削除されます(スペースは削除されません)。使用-Tするオプションmvこれを回避するために
pqnet

これは機能しますが、課題では、付録はあなた次第だと言いました。+1
M.Herzkamp 14

4

NodeJS – 209バイト、3つの空白

s=require('fs');function a(d){s.readdirSync(d).forEach(function(f){f=d+'/'+f;i=0;r=f;if(/ /.test(f)){r=f.replace(' ','');while(s.existsSync(r))r+=i++;s.renameSync(f,r)}s.statSync(r).isDirectory()&&a(r)})}a('.');

node.jsに慣れていません。どのように実行しますか?
M.ヘルツカンプ14

Node実行可能ファイルnodejsが必要です。ファイルに保存して実行node file.js
CPU1

7
例外が発生しTypeError: Object #<Object> has no method 'exists'ます。どこにあると思いますか:1行目です!:D
M.ヘルツカンプ14

私はそれをテストしました。とにかく、私は存在をその同期の対応物に置き換えました。今すぐ試せますか?
cPu1 14

1
バージョン0.6.12のみがインストールされています。それが問題かもしれません。
M.ヘルツカンプ14

2

バッシュ-86バイト

find    .   -d|while    IFS=""  read    f;do    t=${f##*/};mv   --b=t   -T  "$f"    "${f%/*}"/${t// /};done

おっと、見てください
Subbeh 14

2
また、スペースは2回カウントされます
;

スペースが2回カウントされるとはどういう意味ですか?
サブベ

1
あなたは略して文字を大幅に節約することができます--backup--b

1
はい、今では私のテストセットでも動作します!+1
M.ヘルツカンプ14

2

Bash + Perl rename64

renameDebianおよび派生製品のPerlスクリプトであり、util-linuxコマンドではありません。)

find . -depth -name "* *" -execdir rename 'y/ /_/' * \;

11
「my file.txt」と「my_file.txt」の両方が存在する場合はどうなりますか?
M.ヘルツカンプ14

1
ああ、本当です。すぐにその作業中
german_guy 14

1
*{}これは、現在のディレクトリに名前が表示されるファイルの名前を変更するだけなので、である必要があります。これは、衝突の場合に接尾辞を追加しません。名前を変換しないファイルを静かに無視する-name "* *"ため、省略することでかなり節約できますrename
ジル 'SO-悪であるのをやめる' 14

2

POSIX sh+ GNU find+ GNU mv67 ASCIIバイト+ 1 (リテラル)スペース

find    -d  -exec   sh  -cf 'IFS=\ ;IFS=_   set $0;mv   --b=t   "$0"    "$*"'   {}  \;

収まるかどうかはわかりませんが、これを使用すると、スペースのシーケンスが1つに省略され_ます。とにかく気に入っています。実際には、先頭と末尾のスペース以外のシーケンスはすべて-自動的に切り捨てられます(これも有益な動作だと思います)。これを指摘してくれたGillesに感謝します。

これは、フィールドを区切るために内部フィールドセパレーターを使用するだけです。

それはかなり... おしゃべり ...

...ちょっと、あなた。タブが安価であることは知っていましたが、少なくとも賢いと思いました。今、私はパーティーにちょうど遅れています...


これは私のテストセットで意図したとおりに機能しますが、チャレンジが要求するものではありません。私はそれが好きです。なぜなら、おそらく新しいことを学ぶからです。私は、この上に読まなければならないと思いますIFS...魔法のブツ
M.Herzkamp

1
@ M.Herzkamp-ifsは、空白に設定されているかどうかによって動作が異なります。ほとんどの人は、その2つの主要な特性を理解していないため、それが嫌いです。拡張機能(($expand pand )ではなく)と、上記のifswsでのみ機能するということです。見てここに
mikeserv

名前にスペースが含まれるディレクトリ内のファイルの名前は変更されません。修正はに置き換える-execこと-execdirです。IFS言及していないもう1つの癖は、末尾のスペースが削除されることです。他の人が気づいたように、呼び出しの対象が既存のディレクトリである場合にも-Tオプションが必要であることに注意してください。mvmv
ジル 'SO-悪であるのをやめる' 14

@Gilles-私の好みはsh -c 'mkdir -p ../newtree/"$0"; ln "$0"/* ../newtree/$0 {} \;find -type dコマンドで他のグロブを使用してミラーリングされたハードリンクのツリーを作成し、それらを操作することですが、移動操作のためにコードゴルフを書くことは次第に推測します。リーディング/トレーリングスペースについての良い点ですが、それも私が好む行動だと思います。
mikeserv 14

@Gilles -しかし途中で、そうではありません -それは意図している標準コントロールの挙動。フィールド分割セクションには、言葉が含まれていないシェルの仕様では非常に少数の中で、不特定または実装定義します。たとえば、zsh組み込み関数 zmvにはそのような保証はありません。
mikeserv 14

2

PHP、147 145バイト、2 1スペースs- > 146

function    s(){foreach(glob("*")as$n){is_dir($n)&&chdir($n)&s()|chdir("..");if($n<$r=strtr($n," ",_)){while(file_exists($r))$r.=_;rename($n,$r);}}}

再帰関数。で実行s(".");

glob指定されたパスの結果をループします。

  • ディレクトリの場合、再帰
  • スペースをアンダースコアに置き換えます
  • 文字列が異なる場合
    • 新しいファイル名が取得されている間、アンダースコアを追加します
    • ファイル/ディレクトリの名前を変更する

phpはサーバー上のファイルの名前を変更します...クライアントがサイトにアクセスするたびに、クライアントのファイル名を変更する方法を考えます:D
M.Herzkamp

1

ルビー121

require 'find'

Find.find('.') do |file|
  if file.chomp.match(/ /)
    File.rename(file, file.gsub(/ /, '_'))
  end
end

6
コードゴルフへようこそ!これらのコードゴルフの課題におけるここでの考え方は、使用する文字数を最小限にすることです。つまり、空白行とタブを間違いなく取り除き、変数名を単一文字にすることができますが、人々は文字数を減らすためにあらゆる種類創造的な方法を探します。
はないチャールズ

私は、ディレクトリが空でないこと、エラーが発生します:gam3.rb:5:in `rename': Directory not empty - ./Te stSub or ./Te_stSub (Errno::ENOTEMPTY) from gam3.rb:5 from /usr/lib/ruby/1.8/find.rb:39:in `find' from /usr/lib/ruby/1.8/find.rb:38:in `catch' from /usr/lib/ruby/1.8/find.rb:38:in `find' from gam3.rb:3
M.Herzkamp

1

パイソン、187

165、およびスペースの22ペナルティポイント。

from os import*
u='_';j=path.join
for t,d,f in walk('.',0):
 for z in f+d:
  n=z.replace(' ',u)
  if n!=z:
   while path.exists(j(t,n)):n+=u
   rename(j(t,z),j(t,n))

166、エマヌエーレの \ tトリックを使用:

この中に1つだけのスペースがあります!

from    os  import*
u='_';j=path.join
for t,d,f   in  walk('.',0):
    for z   in  f+d:
        n=z.replace(' ',u)
        if  n!=z:
            while   path.exists(j(t,n)):n+=u
            rename(j(t,z),j(t,n))

これは私のために動作します。+1
M.Herzkamp 14

ラインおよび使用タブの先頭にスペースを削除-彼らは、スペースではないので、一度だけカウント
chill0r

@ chill0rそれが2番目のバージョンです。1つを除くすべてのスペースはタブに置き換えられます(SOがスペースとして表示する場合を除く)。
ヘンリーキーター14


0

Bash 4+ 111バイト

shopt -s dotglob globstar
for f in **
do
n=${f// /}
while [[ $f != $n && -e $n ]]
do n+=1
done
mv "$f" $n
done

1
他のいくつかのエントリと同じ問題:親ディレクトリのスペースを置き換えますが、mvはそれらを見つけることができません。また、変換の方向を変更する必要があります。そうしないと、ディレクトリの名前を変更すると、mvは内部のファイルを見つけることができません。
M.ヘルツカンプ14

0

Groovy、139文字

def c
c={
f->
def g=new File(f.parent,f.name.replaceAll('\\s',''))
f.renameTo(g)
!g.directory ?: g.eachFile(c)
}
new File('.').eachFile(c)

@ edc65コメントによると

Groovy、衝突の処理、259文字

def c
c={
p,l,f->
def g=new File(p,f.name.replaceAll('\\s',''))
f==g?:
(g.exists()?f.renameTo(g.toString()+l.indexOf(f.name)):f.renameTo(g))
!g.directory?:g.eachFile(c.curry(g,g.list().toList()))
}
def r=new File('.')
r.eachFile(c.curry(r,r.list().toList()))

1
これは衝突を処理しません。
edc65 14

親ディレクトリが変更される前にファイルの名前が変更され、親ディレクトリのスペースが置き換えられないことを確認してください。
M.ヘルツカンプ

大丈夫だと確信してい
ます

0

POSIX(zshでテスト済み)+基本的なLinuxコマンド151

export IFS='
'
for f in $(ls -R1);do export n=$(echo $f|tr ' ' '_');yes n|mv $f $n || yes n|mv $f `echo $n;echo $f|md5sum`
done

@ M.Herzkamp修正。
LinGeek

いくつかのこと:エクスポートIFSとls -cRのcの機能は何ですか?--replyオプションにはどのバージョンのmvが必要ですか?(8.13があり、オプションを認識しません)。また、より良いスコアを得るには、変数名を短縮する必要があります。
M.Herzkamp

cはスペースを改行に置き換えます。IFSは、スペースが区切り文字になるのを防ぎます。--replyは古いバージョンのものであり、修正される予定です。
LinGeek

1
5行目に2番目のmvがありませんか?そして、私はその行の1つのエコーが間違っていると思う。
M.ヘルツカンプ14

1
$(ls -CR)完全に偽物です。この-cオプションは無意味であり-R、ディレクトリなしでファイルを取得しますが、これは無意味です。基本的に、アーキテクチャは改行を含むファイル名を処理しません。必要な場合、set -fまたはワイルドカードを含むファイル名が爆発します。export役に立たない。ファイルを一意にするために何をしようとしているのか、あいまいに見えますが、パイピングは間違っています。
ジル「SO-悪であるのをやめる」14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.