web-dev-qa-db-ja.com

Linuxですべてのフォルダーとファイルの名前を小文字に変更するにはどうすればよいですか?

完全なフォルダーツリーの名前を再帰的に変更して、大文字がどこにも表示されないようにする必要があります(C++ソースコードですが、それは問題ではありません)。 CVSおよびSVN制御ファイル/フォルダーを無視するためのボーナスポイント。シェルはどのLinuxボックスでも使用できるため、好ましい方法はシェルスクリプトです。

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

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

  2. 私はA-Z文字を検討し、それらをa-zに変換します、他のすべては問題を引き起こしています(少なくともソースコードで)。

  3. Linuxシステムでビルドを実行するにはスクリプトが必要なので、CVSまたはSVN制御ファイルへの変更は省略すべきだと思います。結局のところ、それは単なるスクラッチチェックアウトです。たぶん「輸出」がより適切です。

158
vividos

"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

P. S.

後者の場合、移動コマンドでより柔軟になります(例:"svn mv")。

160
Alex B

まだ小さい

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

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

rename -f 'y/A-Z/a-z/' *
241
tristanbailey
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
83
Swaroop C H

効率を気にする必要がない場合は、単にフォローしてみてください。

Zip -r foo.Zip foo/*
unzip -LL foo.Zip
72
Ginhing

上記の回答のほとんどは、奇妙な文字を含む名前を扱っていないため危険です。この種のことに対する最も安全な方法は、findの-print0オプションを使用することです。このオプションは、\ nの代わりにASCII NULでファイル名を終了します。ここで、このスクリプトを送信します。このスクリプトは、ディレクトリ名ではなくファイルのみを変更し、検索を混乱させないようにします。

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"'

私はそれをテストし、スペース、あらゆる種類の引用符などを含むファイル名で動作します。これは重要です。

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

...よく推測してください...

14
niXar

君たちは、物事を複雑にしたい。

「y/A-Z/a-z /」の名前を変更*

13
Stephen

renameコマンドを既に持っているかセットアップしている場合に機能します(例:Macでbrew installを使用):

rename --lower-case --force somedir/*
12
alemol

これは、CentOS/Redhatまたはrename Perlスクリプトなしの他のディストリビューションで機能します。

for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done

ソース: https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-characters

(一部のディストリビューションでは、デフォルトのrenameコマンドはutil-linuxからのもので、これは別の互換性のないツールです)

7
Pere

元の質問では、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 '{}'  \;

イアン

4
Ian Dickinson

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」を使用することを好みました。

4
vividos

ラリーウォールのファイル名フィクサーの使用

$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/'

(修正はもちろん上記のスクリプトです)

4
agnul

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

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アクションに注意してください。

3
tzot

以前に投稿されたものは、そのままでも完璧に機能しますが、簡単な場合にはいくつかの調整が必要ですが、バッチ名前変更を実行する前に考慮したい状況がいくつかあります。

  1. ABCdefabcDEFaBcDeFなど、大文字と小文字のみが異なるパス階層の同じレベルに2つ以上の名前がある場合はどうなりますか?名前変更スクリプトを中止するか、警告して続行する必要がありますか?

  2. US-ASCII以外の名前に小文字をどのように定義しますか?そのような名前が存在する可能性がある場合、最初にチェックと除外パスを実行する必要がありますか?

  3. CVSまたはSVN作業コピーで名前変更操作を実行している場合、ファイル名またはディレクトリ名の大文字と小文字を変更すると、作業コピーが破損する可能性があります。スクリプトは、.svn/entriesやCVS/Entriesなどの内部管理ファイルも見つけて調整する必要がありますか?

2
for f in `find -depth`; do mv ${f} ${f,,} ; done

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

2

MacOSでは、

renameパッケージをインストールし、

brew install rename

つかいます、

find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"                       

このコマンドは、*.py拡張子を持つすべてのファイルを検索し、ファイル名を小文字に変換します。

`f` - forces a rename

例えば、

$ find . -iname "*.py" -type f
./sample/Sample_File.py
./sample_file.py
$ find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"
$ find . -iname "*.py" -type f
./sample/sample_file.py
./sample_file.py
2
akilesh raj

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

#!/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])
1
John Foley

OSXでは、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
1
Jonghee Park

私はWindows 7のcygwinセットアップでこれを行う必要があり、上からの提案で構文エラーが発生したことがわかりました(ただし、作業オプションを見逃したかもしれませんが)から直接このソリューションは ubutuフォーラム はできませんでした:-)

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

(nb私は以前に空白をアンダースコアに置き換えていました

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

MacOSXで見つけた最も簡単なアプローチは、 http://plasmasturm.org/code/rename/ から名前変更パッケージを使用することでした。

brew install rename
rename --force --lower-case --nows *

--force宛先名を持つファイルがすでに存在する場合でも名前を変更します。

--lower-caseファイル名をすべて小文字に変換します。

--nowsファイル名内の空白のすべてのシーケンスを単一のアンダースコア文字に置き換えます。

1
Kim T

長いが、「驚きとインストールなしで動作する」

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

1
ndemou

移植性はなく、Zshのみですが、かなり簡潔です。

まず、zmvがロードされていることを確認してください。

autoload -U zmv

また、extendedglobがオンになっていることを確認してください。

setopt extendedglob

次に使用します:

zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'

名前がCVSではないファイルおよびディレクトリを再帰的に小文字にします。

1
benjwadams
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh

ここで説明したより精巧なスクリプトは試していませんが、Synology NASで動作する単一のコマンドラインバージョンはありません。 renameは使用できません。また、findのバリエーションの多くは、既に名前が変更されているパスの古い名前に固執しているようです(たとえば、./FOOの後に./FOO/BAR./FOOの名前を./fooに変更すると、そのパスが無効になった場合でも引き続き./FOO/BARのリストが表示されます)。上記のコマンドは問題なく機能しました。

以下は、コマンドの各部分の説明です。


find . -depth -name '*[A-Z]*'

これは、深さ優先検索(たとえば、.の前に./foo/barをリストする)を使用して、現在のディレクトリから任意のファイルを検索します(./fooを処理するディレクトリに変更します) 、ただし大文字を含むファイルのみ。 -nameフィルターは、絶対パスではなく、ベースファイル名にのみ適用されます。したがって、これは./FOO/BARをリストしますが、./FOO/barはリストしません。 ./FOO/barの名前を変更したくないので、これは問題ありません。ただし、./FOOの名前を変更したいのですが、その名前は後でリストします(これが-depthが重要な理由です)。

このコマンド自体は、最初に名前を変更するファイルを見つけるのに特に役立ちます。完全な名前変更コマンドの後にこれを使用して、ファイル名の衝突またはエラーのためにまだ置き換えられていないファイルを検索します。


sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'

この部分は、findによって出力されたファイルを読み取り、正規表現を使用してmvコマンドでフォーマットします。 -nオプションはsedが入力を印刷するのを停止し、search-and-replace正規表現のpコマンドは置換されたテキストを出力します。

正規表現自体は、最後の/(ファイルのディレクトリ)までの部分と、ファイル名自体の2つのキャプチャで構成されます。ディレクトリはそのまま残りますが、ファイル名は小文字に変換されます。したがって、find./FOO/BARを出力すると、mv -n -v -T ./FOO/BAR ./FOO/barになります。 mv-nオプションは、既存の小文字ファイルが上書きされないようにします。 -vオプションは、変更を行うたびにmvを出力します(または、しない場合-./FOO/barが既に存在する場合、./FOO/BAR -> ./FOO/BARのようなものを出力します。作られた)。ここで-Tは非常に重要です-ターゲットファイルをディレクトリとして扱います。これにより、そのディレクトリが存在する場合に./FOO/BAR./FOO/barに移動しないようにします。

これをfindと一緒に使用して、実行されるコマンドのリストを生成します(実際に実行せずに実行されることを確認するのに便利です)


sh

これは一目瞭然です。生成されたすべてのmvコマンドをシェルインタープリターにルーティングします。 bashまたはお好みのシェルに置き換えることができます。

0
oisyn
( 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

最初にディレクトリの名前を下から上に変更しますsort -r(-depthは使用不可)、次にファイル。次に、find ...- Pruneの代わりにgrep -v/CVSを使用します。大きなディレクトリの場合、for f in ...は一部のシェルバッファーをオーバーフローさせる可能性があります。それを避けるためにfind ... | while readを使用してください。

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

0
pklausner

Arch Linux を使用する場合、 rename パッケージを AUR からインストールできます。これはrenamexmコマンドを/usr/bin/renamexm実行可能ファイルおよびその- manual それとともにページ。

ファイルやディレクトリの名前をすばやく変更するための非常に強力なツールです。

小文字に変換

rename -l Developers.mp3 # or --lowcase

大文字に変換

rename -u developers.mp3 # or --upcase, long option

別のオプション

-R --recursive # directory and its children

-t --test # dry run, output but don't rename

-o --owner # change file owner as well to user specified

-v --verbose # output what file is renamed and its new name

-s/str/str2 # substite string on pattern

--yes # Confirm all actions

サンプルを取得できますDevelopers.mp3ファイル here 、必要に応じて;)

0
user4104817

これはmacOSでもうまく機能します:

Ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
0
Chris

Slugify Rename(正規表現)

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

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

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
0
cwd

組版を提案する人はいませんか?

typeset -l new        # always lowercase
find $topPoint |      # not using xargs to make this more readable
  while read old
  do mv "$old" "$new" # quotes for those annoying embedded spaces
  done

Git bashのようなWindowsエミュレーションでは、Windowsはフードの下で大文字と小文字を区別しないため、これは失敗する可能性があります。これらの場合、最初に「$ old.tmp」などの別の名前にファイルをmvするステップを追加し、次に$ newに追加します。

0
Paul Hodges