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

StackOverflow https://stackoverflow.com/questions/152514

  •  02-07-2019
  •  | 
  •  

質問

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

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

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

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

役に立ちましたか?

解決

" 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" )。

他のヒント

まだ小さいですが、とても気に入っています

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

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

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

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

zip -r foo.zip foo/*
unzip -LL foo.zip

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

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "
touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash
")/$(basename "<*>"); d=$(dirname "<*>")/$(basename "<*>"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'

テストし、スペースを含むファイル名、あらゆる種類の引用符などで動作します。これは、次の方法で作成されたファイルを含むツリー上で他のスクリプトの1つをルートとして実行すると重要です。 > <*>

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

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

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

複雑なことをやりたいと思う人..

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

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

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

出典: https://linuxconfig.org/rename-大文字から小文字までのすべてのファイル

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

Larry Wallのファイル名フィクサーの使用

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = 

Larry Wallのファイル名フィクサーの使用

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

と同じくらい簡単です

<*>

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

; eval $op; die $@ if $@; rename($was,

Larry Wallのファイル名フィクサーの使用

<*>

と同じくらい簡単です

<*>

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

) unless $was eq

Larry Wallのファイル名フィクサーの使用

<*>

と同じくらい簡単です

<*>

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

; }

と同じくらい簡単です

<*>

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

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

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

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

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

イアン

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制御ファイルの名前は変更されます)。

編集:&quot; find -depth&quot;以降および&quot; find | sort -r&quot;どちらも、名前を変更するために使用可能な順序でフォルダリストを返します。フォルダーの検索用。

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

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

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

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

  1. パス階層の同じレベルに複数の名前があり、大文字と小文字のみが異なる場合、 ABCdef abcDEF aBcDeF ?名前変更スクリプトを中止するか、警告して続行する必要がありますか?

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

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

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

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

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

ポータブルではなく、Zshのみですが、かなり簡潔です。

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

autoload -U zmv

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

setopt extendedglob

次に使用:

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

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

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

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

スペースやスラッシュのないパスを楽観的に仮定することを避けるために、この状況では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])

長いが&quot;驚きのない動作&&;インストールなし&quot;

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

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

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

-宛先名のファイルがすでに存在する場合でも、名前を強制的に変更します。

     

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

     

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

( 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 を使用する方が簡単です。 大きなディレクトリの場合、 f in ... は一部のシェルバッファをオーバーフローさせる可能性があります。 find ...を使用します|それを避けるために読みながら

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

Slugify Rename(regex)

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

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

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

Arch Linux を使用する場合、 rename パッケージ.org / packages / rename "rel =" nofollow noreferrer "> renamexm コマンドを / usr / bin / renamexm AUR >実行可能ファイルとそのマニュアルと一緒に。

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

小文字に変換

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

タイプセットを提案する人はいませんか?

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はフードの下で大文字と小文字を区別しないため、これは失敗する可能性があります。これらの場合、最初に&quot; $ old.tmp&quot;などの別の名前にファイルをmvするステップを追加し、次に$ newに追加します。

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

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
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 に変更しても、引き続き< code> ./ 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 regexの p コマンドは置換されたテキストを出力します。

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

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


sh

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top