216

フォルダー ツリー全体の名前を再帰的に変更して、大文字がどこにも表示されないようにする必要があります (これは C++ ソース コードですが、問題にはなりません)。

CVS および Subversion のバージョン管理ファイル/フォルダーを無視するためのボーナス ポイント。シェルは任意の Linux ボックスで使用できるはずなので、シェル スクリプトを使用することをお勧めします。

ファイルの名前変更の詳細については、いくつかの有効な議論がありました。

  1. 同じ小文字の名前のファイルは上書きする必要があると思います。それはユーザーの問題です。大文字と小文字を区別しないファイル システムでチェックアウトすると、最初のものも後者で上書きされます。

  2. 私は AZ 文字を検討し、それらを az に変換します。それ以外はすべて問題を引き起こしているだけです (少なくともソース コードでは)。

  3. Linux システムでビルドを実行するにはスクリプトが必要になるため、CVS または Subversion のバージョン管理ファイルへの変更は省略すべきだと思います。結局のところ、それは単なるスクラッチ チェックアウトです。「輸出」の方が適切かもしれません。

4

29 に答える 29

294

小さいですが、私はかなり気に入っています:

rename 'y/A-Z/a-z/' *

OS X のHFS+などの大文字と小文字を区別しないファイルシステムでは、次の-fフラグを追加する必要があります。

rename -f 'y/A-Z/a-z/' *
于 2011-11-17T12:30:58.723 に答える
194

"rename"次のコマンドを使用した簡潔なバージョン:

find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

これにより、ファイルの前にディレクトリの名前が変更されたり、ファイルを存在しないディレクトリ (たとえば ) に移動しようとしたりする問題が回避され"A/A"ます"a/a"

または、を使用しないより詳細なバージョン"rename"

for SRC in `find my_root_dir -depth`
do
    DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
    if [ "${SRC}" != "${DST}" ]
    then
        [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
    fi
done

PS

後者では、移動コマンド ( など) をより柔軟に使用できます"svn mv"

于 2008-09-30T12:03:32.720 に答える
107
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
于 2008-09-30T10:36:08.637 に答える
17

これは、名前変更コマンドを既に持っているか、設定している場合に機能します(例: Mac でbrew installを使用):

rename --lower-case --force somedir/*
于 2015-11-09T21:08:42.557 に答える
15

上記の回答のほとんどは、奇妙な文字を含む名前を扱っていないため、危険です。この種のことに対する最も安全な方法は、\n の代わりに ASCII NUL でファイル名を終了するfind'sオプションを使用することです。-print0

混乱しないように、ディレクトリ名ではなくファイルのみを変更するスクリプトを次に示しますfind

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "$0")/$(basename "$0");
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'

私はそれをテストしましたが、スペースやあらゆる種類の引用符などを含むファイル名で動作します。これは重要です。なぜなら、ルートとして、によって作成されたファイルを含むツリーで他のスクリプトの 1 つを実行すると

touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash

...まあ、何だと思いますか...

于 2008-09-30T12:34:13.580 に答える
5

Bash シェル スクリプトを使用した、次善のソリューションを次に示します。

#!/bin/bash
# First, rename all folders
for f in `find . -depth ! -name CVS -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming folder $f"
      mv -f "$f" "$g"
   fi
done

# Now, rename all files
for f in `find . ! -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming file $f"
      mv -f "$f" "$g"
   fi
done

フォルダの名前はすべて正しく変更され、mvパーミッションが一致しない場合でも質問はされず、CVS フォルダの名前は変更されません (残念ながら、そのフォルダ内の CVS 制御ファイルの名前は変更されたままです)。

"find -depth" と "find | sort -r" はどちらも名前変更に使用できる順序でフォルダー リストを返すため、フォルダーの検索には "-depth" を使用することを好みました。

于 2008-09-30T10:27:20.437 に答える
5

一発ギャグ:

for F in K*; do NEWNAME=$(echo "$F" | tr '[:upper:]' '[:lower:]'); mv "$F" "$NEWNAME"; done

あるいは:

for F in K*; do mv "$F" "${F,,}"; done

これは文字 K で始まるファイル/ディレクトリのみを変換することに注意してください。したがって、それに応じて調整してください。

于 2020-11-18T18:26:31.933 に答える
4

Larry Wall のファイル名修正プログラムを使用:

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

それは次のように簡単です

find | fix 'tr/A-Z/a-z/'

fixもちろん、上記のスクリプトはどこにありますか)

于 2008-09-30T10:50:14.500 に答える
4

元の質問では、SVN および CVS ディレクトリを無視するよう求められました。これは、find コマンドに -prune を追加することで実行できます。たとえば、CVS を無視するには:

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[編集] これを試してみましたが、検索内に小文字の翻訳を埋め込むことは、実際には理解できない理由で機能しませんでした。したがって、これを次のように修正します。

$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower 
$> find . -name CVS -prune -o -exec tolower '{}'  \;

イアン

于 2008-09-30T11:08:29.373 に答える
3

これは、あなたが要求したことを実行する小さなシェル スクリプトです。

root_directory="${1?-please specify parent directory}"
do_it () {
    awk '{ lc= tolower($0); if (lc != $0) print "mv \""  $0 "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it

最初の検索の -depth アクションに注意してください。

于 2008-09-30T10:54:48.767 に答える
3
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depthディレクトリ自体の前にディレクトリの内容を出力して、各ファイルとディレクトリを出力します。${f,,}ファイル名を小文字にします。

于 2016-02-22T18:42:51.307 に答える
2

OS X では、mv -f「同じファイル」エラーが表示されるため、名前を 2 回変更します。

for i in `find . -name "*" -type f |grep -e "[A-Z]"`; do j=`echo $i | tr '[A-Z]' '[a-z]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done
于 2015-03-25T06:25:39.747 に答える
2

長くなりますが、「驚きやインストールなしで動作します」

このスクリプトは、スペース、引用符、その他の特殊な文字および Unicode を含むファイル名を処理し、大文字と小文字を区別しないファイルシステムと、 bash と awk がインストールされているほとんどの Unix-y 環境 (つまり、ほぼすべて) で動作します。また、衝突があれば報告し (ファイル名は大文字のまま)、もちろんファイルとディレクトリの両方の名前を変更し、再帰的に動作します。最後に、非常に適応性があります。find コマンドを微調整して、必要なファイル/ディレクトリをターゲットにすることができ、awk を微調整して他の名前操作を行うことができます。「Unicodeを処理する」とは、実際に大文字と小文字を変換することを意味することに注意してください(を使用する回答のように無視しないでくださいtr)。

# adapt the following command _IF_ you want to deal with specific files/dirs
find . -depth -mindepth 1 -exec bash -c '
  for file do
    # adapt the awk command if you wish to rename to something other than lowercase
    newname=$(dirname "$file")/$(basename "$file" | awk "{print tolower(\$0)}")
    if [ "$file" != "$newname" ] ; then
        # the extra step with the temp filename is for case-insensitive filesystems
        if [ ! -e "$newname" ] && [ ! -e "$newname.lcrnm.tmp" ] ; then
           mv -T "$file" "$newname.lcrnm.tmp" && mv -T "$newname.lcrnm.tmp" "$newname" 
        else
           echo "ERROR: Name already exists: $newname"
        fi
    fi    
  done
' sh {} +

参考文献

私のスクリプトは、次の優れた回答に基づいています。

https://unix.stackexchange.com/questions/9496/looping-through-files-with-spaces-in-the-names

Bashで文字列を小文字に変換するには?

于 2018-09-24T12:12:21.570 に答える
1

Windows 7のCygwinセットアップでこれを行う必要があり、上記の提案で試した構文エラーが発生することがわかりました(ただし、動作するオプションを見逃した可能性があります)。ただし、Ubuntuフォーラムからのこのソリューションはすぐに機能しました:-)

ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done

(注:以前に、次を使用して空白をアンダースコアに置き換えました:

for f in *\ *; do mv "$f" "${f// /_}"; done

)

于 2015-01-15T17:43:03.470 に答える
1

この状況では、スペースやスラッシュのないパスを楽観的に想定することを避けるために、Python に手を伸ばします。python2よりも多くの場所にインストールされる傾向があることもわかりましたrename

#!/usr/bin/env python2
import sys, os

def rename_dir(directory):
  print('DEBUG: rename('+directory+')')

  # Rename current directory if needed
  os.rename(directory, directory.lower())
  directory = directory.lower()

  # Rename children
  for fn in os.listdir(directory):
    path = os.path.join(directory, fn)
    os.rename(path, path.lower())
    path = path.lower()

    # Rename children within, if this child is a directory
    if os.path.isdir(path):
        rename_dir(path)

# Run program, using the first argument passed to this Python script as the name of the folder
rename_dir(sys.argv[1])
于 2016-01-31T18:07:20.520 に答える
1

Slugify 名前の変更 (正規表現)

これはまさに OP が要求したものではありませんが、このページで見つけたいと思っていたものです。

ファイルの名前を URL に似たものにするための "slugify" バージョン (つまり、英数字、ドット、およびダッシュのみを含む):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
于 2015-02-28T02:32:26.350 に答える
0
( find YOURDIR -type d | sort -r;
  find yourdir -type f ) |
grep -v /CVS | grep -v /SVN |
while read f; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done

最初にディレクトリの名前を下から上に並べ替え -r (ここでは -depth は使用できません)、次にファイルの名前を変更します。それからgrep -v /CVSの代わりにfind ...-pruneの方が簡単です。大きなディレクトリの場合、for f in ...は一部のシェル バッファをオーバーフローさせる可能性があります。検索を使用... | それを避けるために読んでいる間。

そして、はい、これは大文字と小文字のみが異なるファイルを上書きします...

于 2008-09-30T11:26:32.853 に答える