ファイル名のスペース、ハイフン、アンダースコアを削除しますか?


10

ディレクトリ内のすべてのファイル、または選択したファイルからスペース、ハイフン、アンダースコアを削除するための適切なコマンドは何ですか?

Thunarカスタムアクションで次のコマンドを使用して、ファイル名をスラッグ化します。

for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done

ただし、このコマンドは、スペースをダッシュ​​/ハイフンと小文字の大文字に置き換えるだけです。

ターミナルで次のコマンドを使用して、フォルダー内の数千のファイル名からスペースを削除しました。

 rename "s/ //g" *

この場合も、スペースのみが削除され、ハイフン/ダッシュやアンダースコアは削除されません。

理想的には、ファイル名にスペース、ハイフン/ダッシュ、アンダースコアを使用したくない。また、選択したファイルのThunarカスタムアクションでコマンドを使用できると便利です。


2
提案された解決策の多くにある1つの問題は、ファイルをmvする前に「新しい」名前の存在を適切にチェックしないことです。そうしないと、多くの問題の潜在的な原因になる可能性があります。
mdpc 2014

それを確認するためにJohn1024のコマンドを変更することは可能ですか?
user8547 14

@ user8547rename -i "s/[-_ ]//g" *
Sparhawk

Sparhawkさん、ありがとうございます。ちなみに、これをThunarカスタムアクションとして使用することに関心のある人にとって、Thunarのコマンドは次のとおりです。mv "$ file"を実行しますecho $file | sed -e 's/[ _-]//g'。完了
user8547 2014

回答:


11

パッケージにrename付属するのバージョンは、perl正規表現をサポートしています。

rename "s/[-_ ]//g" *

または、

rename -i "s/[-_ ]//g" *

この-iフラグはrename対話モードを使用し、ターゲットがすでに存在する場合は、メッセージを表示せずに上書きする代わりにプロンプ​​トを出します。

Perlの名前変更は、と呼ばれることもありprenameます。

Perlの名前変更とutil-linuxの名前変更

Debianのようなシステムでは、perlの名前変更がデフォルトのようであり、上記のコマンドが機能するはずです。

一部のディストリビューションではrename、util-linuxのユーティリティがデフォルトです。このユーティリティは、Perlと完全に互換性がありませんrename

  • すべて:まず、Perl renameがという名前で使用できるかどうかを確認しますprename

  • Debian: Perlの名前変更がデフォルトになっているはずです。としても利用可能ですprenamerename実行可能ファイルは、しかし、の制御下にある/etc/alternativesので、何か別のに変更された可能性があります。

  • archlinux:実行するpacman -S perl-renameと、コマンドはとして利用できますperl-rename。より便利な名前にするには、エイリアスを作成します。(帽子の先端:ChiseledAbs)

  • Mac OSX この回答によれば、renamehomebrewを使用してOSXにインストールできます。

    brew install rename 
  • 直接ダウンロード: rename Perl Monksからも入手できます。

     wget 'http://www.perlmonks.org/?displaytype=displaycode;node_id=303814' -O rename

それrenameはあなたが何を話しているかによると思います。1 のutil-linuxの -2.24.2-1.fc20.x86_64は、正規表現をサポートしていません。
クリスティアンCiupitu 2014

1
@CristianCiupitu見つけたrenameのバージョンをmanページで確認しました。引数に基づいrenameて、OPが使用してperlいたutil-linuxバージョンは、バージョンではなくバージョンのように見えます。
John1024 2014

参考までに、これはutil-linuxバージョンのrenamemanページです。とにかく、そのメモに加えて、重要なことはOPが彼の答えを得たことです(そしてあなたは私からの賛成です:-D)。
クリスティアンCiupitu 2014

@CristianCiupituそれを見つけてくれてありがとう。+1で戻ってきます。
John1024 2014

1
@ John1024 archlinux、しかし私は方法を見つけました、ただ行ってpacman -S perl-renameからエイリアスを付けることができると思います。
ChiseledAbs 2016


4

数えていないmv、あなたは本当にすべてで、このために外部のプロセスを必要としない-あなたはできる種類だけのパッと消えるそれら。

ifsqz() ( LC_ALL=C sqz=$1
    isf() { [ -e "$1" ] || [ -L "$1" ] ; }  
    set -- * ; set -f
    for f do isf "$f" || break
    IFS=$sqz; set -- $f; IFS=
    isf "$*" || mv -- "$f" "$*"
    done
)

それでも、これはmvファイルごとの呼び出しを意味するので、おそらくrenameより良い方法です。これは唯一のPOSIX与えられた動作するはずですけれどもmv$PATHおよびPOSIXシェル。

だから、私はこれのために一種のクレイジーなデモを思いつきました。テストセットは次のように生成されます。

tee - - - - <<CGEN |\
dd cbs=90 conv=unblock |\
sed 'G;$!N'";s/^/touch -- '/;s/$/'/" |sh
$( #BEGIN CGEN
   LC_ALL=C
   i= n='"$((i=((i=i+1)==10||i==39||i==47)>0?(i+1):i))"'
   printf '%b -_   ---___'  $(
   IFS=0; eval \
       printf '"\\\\%04o\\\\%04o "' "$(
       printf "$n"' "$i" '%s $(
       printf %.252d
#END
))"))
CGEN

最初に、上記のコマンドが他の方法でより簡単に取得できる結果を生成することを最初に認めます。しかし、他の方法では、おそらく何が行われるのか、$IFSそして少し(病気ですか?)想像力も実証されないでしょう。

したがって、最初のビットはかなり単純です。

  • tee その入力の5つのコピーをパイプアウトします-ヒアドキュメントは CGEN

  • dd ブロックごとに90バイトで改行によって入力をブロックし、それをパイプして...

  • sedこれらのブロックの2つを2つの\newline文字で'結合し、結果を単一引用符で囲み、touch --パイプラインする前にすべてのラインサイクルの文字列を先頭に追加します...

  • sh 次に、すべての入力をシェルコマンドとして実行します

#CGENビットしかし...まあ、簡単に...

  • 下部printfは252 0sを印刷します

  • next from lastは252個の''null文字列引数を受け取り、それぞれの内容を表示し、$nその後に文字列を続けます" $i "

  • eval次の引数を解釈してから、printfその解釈の結果を2つのバックスラッシュを前に付けた8進数として出力します

  • 最後printfは、これらの8進数のバイト値を一度に2つずつ出力し、その後-_ ---___に各ペアの文字列を出力します

  • $n$i10、39、または47をスキップすることを除いて、評価ごとに1 ずつ増加する方程式に初期化されます(これらはそれぞれ、ASCII 10進数の\newline、'単一引用符、および/スラッシュです)。

最終結果は、単一引用符(1つ以上のsed s///ステートメントを避けるためにスキップされます/スラッシュを除いて、文字セットの1から255までのすべてのバイトを含む非常に醜いファイル名を多く含むディレクトリです。これらのファイル名は次のようになります。

(set -- *; printf '%s\n\n##############\n\n%s\n' "${9}" "${34}")  | cat -A

   ---___ww -_   ---___xx -_   ---___yy -_   ---___zz -_   ---___{{ -_   ---___|| -_   ---$
$
___}} -_   ---___~~ -_   ---___^?^? -_   ---___M-^@M-^@ -_   ---___M-^AM-^A -_   ---___M-^BM-^B -_   ---___M-^CM-^C$
$
##############$
$
 -_   ---___M-ZM-Z -_   ---___M-[M-[ -_   ---___M-\M-\ -_   ---___M-]M-] -_   ---___M-^M-^ -_   ---___M-_M-_ -_$
$
---___M-`M-` -_   ---___M-aM-a -_   ---___M-bM-b -_   ---___M-cM-c -_   ---___M-dM-d -_   ---___M-eM-e -_   ---___$

次に、これらのファイルに関するデータを取得します。

chksqz() ( LC_ALL=C sqz=$1
    set -- * ; set -f ; IFS= ; tc="$*"
    printf '#%s\n' \
        "There are $# files in this test directory." \
        "All filenames combined contain a total of ${#tc} bytes."
    IFS=$sqz ; set -- $* ; IFS= ; sc="$*"  
    printf "%s '$sqz'" \
        "#Of which ${#sc} bytes are not"\
        " and $((${#tc}-${#sc})) bytes are"
    set +f ; unset IFS
    printf ".\n#%s\n#Total:\t%d\n#Other:\t%d\n#'$sqz':\t%d\n" \
        "And to confirm these figures:" \
        $(  printf %s * | wc -c 
            printf %s * | tr -d "$sqz" | wc -c
            printf %s * | tr -dc "$sqz" | wc -c
))
chksqz '_ -'

出力

#There are 101 files in this test directory.
#All filenames combined contain a total of 17744 bytes.
#Of which 2692 bytes are not '_ -' and 15052 bytes are '_ -'.
#And to confirm these figures:
#Total: 17744
#Other: 2692
#'_ -': 15052

OK。最後に、アクションに:

ifsqz '_ -'
chksqz '_ -'

出力

#There are 101 files in this test directory.
#All filenames combined contain a total of 2692 bytes.
#Of which 2692 bytes are not '_ -' and 0 bytes are '_ -'.
#And to confirm these figures:
#Total: 2692
#Other: 2692
#'_ -': 0

成功!あなたはあなた自身のために見ることができます:

ls

????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????
??????????????????????
????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
??????????????????????????
????????????????????????
????????????????????
??????????????????
????????????????????????????
??
????????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????
????????????????????!!""##
??????????????????!!""##$$
????????????????!!""##$$%%
????????????!!""##$$%%&&((
????????!!""??##$$%%&&(())
$$%%&&(())**??++,,..0011
%%&&(())**++??,,..00112233
&&(())**++,,??..0011223344
))**++,,..??0011223344556
**++,,..00??11223344556677
22334455667788??99::;;<<==>>
445566778899??::;;<<==>>??@@
5566778899::;;??<<==>>??@@AA
6778899::;;<<??==>>??@@AABB
8899::;;<<==??>>??@@AABBCCDD
\\]]^^``aa??bbccddeeffgghh
]]^^``aabbc??cddeeffgghhii
^^``aabbccdd??eeffgghhiijj
??@@AABBCCDDEE??FFGGHHIIJJKK
AABBCCDDEEFF??GGHHIIJJKKLLM
BBCCDDEEFFGG??HHIIJJKKLLMMNN
CCDDEEFFGGHHII??JJKKLLMMNNOO
EEFFGGHHIIJJ??KKLLMMNNOOPPQQ
ffgghhiijjkk??llmmnnooppqqrr
gghhiijjkkllmm??nnooppqqrrss
iijjkkllmmnn??ooppqqrrsstt
jjkkllmmnnoo??ppqqrrssttuuvv
kkllmmnnooppqq??rrssttuuvvww
LLMMNNOOPPQQRR??SSTTUUVVWWXX
MNNOOPPQQRRSS??TTUUVVWWXXYY
OOPPQQRRSSTT??UUVVWWXXYYZZ[[
PPQQRRSSTTUUVV??WWXXYYZZ[[\\
RRSSTTUUVVWW??XXYYZZ[[\\]]
ssttuuvvwwxx??yyzz{{||}}~~??
ttuuvvwwxxyyz??z{{||}}~~????
uuvvwwxxyyzz{{??||}}~~??????
wwxxyyzz{{||??}}~~??????????
xxyyzz{{||}}~~??????????????
YYZZ[[\\]]^^??``aabbccddee
ZZ[[\\]]^^``??aabbccddeeff

2
+の創造的な使用のためのIFS+1printf
John1024 '

@ John1024-何が本当に楽しいか:set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
mikeserv

1
new="$(IFS=" -_"; printf %s $1)"サブシェルをフォークし(ksh93を除く)、改行の末尾に問題があります。別のオプションは使用することですIFS=' -_'; set -- $1; IFS=; new="$*"(とループのためにあなたのwhileループを変更)
ステファンChazelas

1
[ -e x ]x存在しない、またはアクセスできないファイルへのシンボリックリンクの場合、falseを返します。
ステファンChazelas

1
ナイスシェルカンフー!
カウンター

2

perlがある場合、通常は名前を変更します。できるよ:

> type rename
rename is /usr/bin/rename

このスクリプトの記述方法を示します。

> cat /usr/bin/rename | head -n 5 #firt 5 lines for example
#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#

このスクリプトは-iフラグ(これは私のシステムのバージョンです)をサポートしていませんが、おそらくサポートしています。引数についてはどうでしょう。最初はPCRE形式の正規表現で、フィルターのように機能し、入力名を出力名に変更します。アスタリスク「*」で指定した入力名のリスト。たとえば、次のようにします。

> cd /tmp
> rename 's/ //g' *

実際には「*」は次のように展開できます。

> rename 's/ //g' file1 file2 file3 othe files found in current directory

あなたが本当に大きな数のファイルを持っているとき、あなたは罠にかかっています。シェルはシステムが受け入れるよりも長くあなたの行を拡張します。その後、findまたはxargsを使用して回避策を実行できます。名前の変更は、ディレクトリ内のファイル数と同じ回数だけ呼び出されるため、「検索」の使用は問題です。xargsを-rオプションとともに使用することをお勧めします。1つの名前変更呼び出しで多くのファイルが変更されます。例えば:

> ls | xargs -r rename 's/ //g'   #thats all, names will be appended at the end of this command.

最後の問題、それはどういう意味ですか:

's/ //g'

これは、名前を変更するための正規表現です。最初の「/」の後はスペースです。これが検出され、2番目の「/」の後の文字列に置き換えられます。しかし、3番目の「/」で終わる空の文字列があり、スペースは何も置き換えられません。オプション「g」は、この表現を繰り返します。式は、最初から最後まですべての名前を検索し、すべてのスペースを検出します。

しかし、タブ文字やその他の「白い」文字がある場合はどうでしょうか。この「\ s」に代わるものがあります。他にどのような不要な文字?式に追加するだけです。括弧ですべて閉じます。次に例を示します。

's/[\s_-]//g'

これですべてです。似ていると思いますか man perlrequickとman perlretutを読むべきだと思います、これは正規表現がどのように機能するかを説明します(私は願っています)。必要に応じて、独自のスクリプトでrenameコマンドを使用できます。


1

次のshシェルループは、既存のファイルを上書きしないように注意して、現在のディレクトリ内のファイル名からすべてのスペース、アンダースコア、ダッシュを削除します。

for f in *; do
    test -f "$f" || continue
    nf=$( echo "$f" | tr -d ' _-' )
    ! test -e "$nf" && echo mv "$f" "$nf"
done

以下のためにbashksh、ロジックと少し冗長であること:

for f in *; do
    if [[ -f "$f" ]]; then
        nf=$( tr -d ' _-' <<<"$f" )
        if [[ ! -e "$nf" ]]; then
            echo mv "$f" "$nf"
        fi
    fi
done

echo実行したいことが確実に実行されたら、を削除してください。

trコマンドが(削除される-d文字の特定のセットで)任意の文字を(' _-')。セットの最初または最後にダッシュを置くことが重要です。そうしないと、一連の文字として解釈されます。

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