IT박스

Linux에서 모든 폴더와 파일의 이름을 소문자로 바꾸려면 어떻게합니까?

itboxs 2020. 6. 1. 19:28
반응형

Linux에서 모든 폴더와 파일의 이름을 소문자로 바꾸려면 어떻게합니까?


대문자 폴더가 어디에도 나타나지 않도록 전체 폴더 트리의 이름을 재귀 적으로 바꿔야합니다 (C ++ 소스 코드이지만 중요하지는 않습니다).

CVS 및 Subversion 버전 제어 파일 / 폴더를 무시하기위한 보너스 포인트. 쉘은 모든 Linux 상자에서 사용 가능해야하므로 쉘 스크립트가 선호됩니다.

파일 이름 변경에 대한 세부 사항에 대한 몇 가지 유효한 인수가있었습니다.

  1. 소문자 이름이 같은 파일은 덮어 써야한다고 생각합니다. 그것은 사용자의 문제입니다. 대소 문자를 무시하는 파일 시스템에서 체크 아웃하면 첫 번째 파일 시스템도 첫 번째 파일 시스템을 덮어 씁니다.

  2. AZ 문자를 고려하여 az로 변환하고 다른 모든 것은 문제를 요구합니다 (적어도 소스 코드 사용).

  3. 스크립트는 Linux 시스템에서 빌드를 실행하는 데 필요하므로 CVS 또는 Subversion 버전 제어 파일에 대한 변경은 생략해야한다고 생각합니다. 결국, 그것은 단지 스크래치 체크 아웃입니다. 아마도 "수출"이 더 적합 할 것입니다.


"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

추신

후자는 이동 명령 (예 :)으로 더 많은 유연성을 허용 "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대신 ASCII NUL와 파일 이름을 종료합니다 \ n 옵션을.

다음은 혼동하지 않도록 디렉토리 이름이 아닌 파일 만 변경하는 스크립트입니다 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"'

나는 그것을 테스트했고, 공백, 모든 종류의 따옴표 등을 포함하는 파일 이름으로 작동합니다. 루트로 실행하면 파일을 포함하는 트리에서 다른 스크립트 중 하나를 루트로 실행할 경우 중요합니다.

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

... 잘 생각 해봐 ...


얘들 아, 너희들 / 여자들은 복잡한 것들을 지나치게 좋아한다.

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

rename 명령 이 이미 있거나 설정 한 경우 (예 : Mac의 brew install통해 ) 다음과 같이 작동합니다.

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

이것은 CentOS / Red Hat Linux 또는 renamePerl 스크립트가 없는 다른 배포판에서 작동합니다 :

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

소스 : 모든 파일 이름을 대문자에서 소문자로 바꿉니다 .

(일부 배포판에서 기본 rename명령은 util-linux에서 제공되며 다른 호환되지 않는 도구입니다.)


원래 질문은 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 '{}'  \;

이안


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"를 사용하는 것이 좋습니다.


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물론 위의 스크립트는 어디에 있습니까 )


이것은 당신이 요청한 것을하는 작은 쉘 스크립트입니다 :

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 조치를 참고하십시오.


이식성이 없으며 Zsh만이 아니라 매우 간결합니다.

먼저 zmv로드되어 있는지 확인하십시오 .

autoload -U zmv

또한 켜져 있는지 확인하십시오 extendedglob.

setopt extendedglob

그런 다음 사용하십시오.

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

이름이 CVS 가 아닌 파일과 디렉토리를 반복적으로 소문자로 변환합니다 .


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

Mac OS X에서 가장 간단한 방법은 http://plasmasturm.org/code/rename/ 에서 이름 바꾸기 패키지를 사용하는 것입니다 .

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

--force 대상 이름을 가진 파일이 이미 존재하더라도 이름을 바꿉니다.

-소문자-파일 이름을 모두 소문자로 변환합니다.

--nows 파일 이름의 모든 공백 문자를 단일 밑줄 문자로 바꿉니다.


Lengthy But "Works With No Surprises & No Installations"

This script handles filenames with spaces, quotes, other unusual characters and Unicode, works on case insensitive filesystems and most Unix-y environments that have bash and awk installed (i.e. almost all). It also reports collisions if any (leaving the filename in uppercase) and of course renames both files & directories and works recursively. Finally it's highly adaptable: you can tweak the find command to target the files/dirs you wish and you can tweak awk to do other name manipulations. Note that by "handles Unicode" I mean that it will indeed convert their case (not ignore them like answers that use 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 {} +

References

My script is based on these excellent answers:

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

How to convert a string to lower case in Bash?


I needed to do this on a Cygwin setup on Windows 7 and found that I got syntax errors with the suggestions from above that I tried (though I may have missed a working option). However, this solution straight from Ubuntu forums worked out of the can :-)

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

(NB: I had previously replaced whitespace with underscores using:

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

)


In OS X, mv -f shows "same file" error, so I rename twice:

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

I would reach for Python in this situation, to avoid optimistically assuming paths without spaces or slashes. I've also found that python2 tends to be installed in more places than 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])

( 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

First rename the directories bottom up sort -r (where -depth is not available), then the files. Then grep -v /CVS instead of find ...-prune because it's simpler. For large directories, for f in ... can overflow some shell buffers. Use find ... | while read to avoid that.

And yes, this will clobber files which differ only in case...


This works nicely on macOS too:

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

I haven't tried the more elaborate scripts mentioned here, but none of the single commandline versions worked for me on my Synology NAS. rename is not available, and many of the variations of find fail because it seems to stick to the older name of the already renamed path (eg, if it finds ./FOO followed by ./FOO/BAR, renaming ./FOO to ./foo will still continue to list ./FOO/BAR even though that path is no longer valid). Above command worked for me without any issues.

What follows is an explanation of each part of the command:


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

This will find any file from the current directory (change . to whatever directory you want to process), using a depth-first search (eg., it will list ./foo/bar before ./foo), but only for files that contain an uppercase character. The -name filter only applies to the base file name, not the full path. So this will list ./FOO/BAR but not ./FOO/bar. This is ok, as we don't want to rename ./FOO/bar. We want to rename ./FOO though, but that one is listed later on (this is why -depth is important).

This comand in itself is particularly useful to finding the files that you want to rename in the first place. Use this after the complete rename command to search for files that still haven't been replaced because of file name collisions or errors.


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

This part reads the files outputted by find and formats them in a mv command using a regular expression. The -n option stops sed from printing the input, and the p command in the search-and-replace regex outputs the replaced text.

The regex itself consists of two captures: the part up until the last / (which is the directory of the file), and the filename itself. The directory is left intact, but the filename is transformed to lowercase. So, if find outputs ./FOO/BAR, it will become mv -n -v -T ./FOO/BAR ./FOO/bar. The -n option of mv makes sure existing lowercase files are not overwritten. The -v option makes mv output every change that it makes (or doesn't make - if ./FOO/bar already exists, it outputs something like ./FOO/BAR -> ./FOO/BAR, noting that no change has been made). The -T is very important here - it treats the target file as a directory. This will make sure that ./FOO/BAR isn't moved into ./FOO/bar if that directory happens to exist.

Use this together with find to generate a list of commands that will be executed (handy to verify what will be done without actually doing it)


sh

This pretty self-explanatory. It routes all the generated mv commands to the shell interpreter. You can replace it with bash or any shell of your liking.


Slugify Rename (regex)

It is not exactly what the OP asked for, but what I was hoping to find on this page:

A "slugify" version for renaming files so they are similar to URLs (i.e. only include alphanumeric, dots, and dashes):

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

If you use Arch Linux, you can install rename) package from AUR that provides the renamexm command as /usr/bin/renamexm executable and a manual page along with it.

It is a really powerful tool to quickly rename files and directories.

Convert to lowercase

rename -l Developers.mp3 # or --lowcase

Convert to UPPER case

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

Other options

-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 # Substitute string on pattern

--yes # Confirm all actions

You can fetch the sample Developers.mp3 file from here, if needed ;)


Use typeset:

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

On Windows, emulations, like Git Bash, may fail because Windows isn't case-sensitive under the hood. For those, add a step that mv's the file to another name first, like "$old.tmp", and then to $new.

참고URL : https://stackoverflow.com/questions/152514/how-do-i-rename-all-folders-and-files-to-lowercase-on-linux

반응형