Làm cách nào để đổi tên tất cả các thư mục và tệp thành chữ thường trên Linux?


179

Tôi phải đổi tên một cây thư mục hoàn chỉnh theo cách đệ quy để không có chữ in hoa xuất hiện ở bất cứ đâu (đó là mã nguồn C ++, nhưng điều đó không quan trọng).

Điểm thưởng cho việc bỏ qua các tệp / thư mục kiểm soát phiên bản CVS và Subversion. Cách ưa thích sẽ là tập lệnh shell, vì shell nên có sẵn trên bất kỳ hộp Linux nào.

Có một số đối số hợp lệ về chi tiết đổi tên tập tin.

  1. Tôi nghĩ rằng các tập tin có cùng tên viết thường nên được ghi đè; đó là vấn đề của người dùng. Khi được kiểm tra trên một hệ thống tập tin bỏ qua trường hợp, nó cũng sẽ ghi đè lên hệ thống tập tin đầu tiên với cái sau.

  2. Tôi sẽ xem xét các ký tự AZ và chuyển đổi chúng thành az, mọi thứ khác chỉ là gọi cho các vấn đề (ít nhất là với mã nguồn).

  3. Kịch bản sẽ là cần thiết để chạy bản dựng trên hệ thống Linux, vì vậy tôi nghĩ rằng các thay đổi đối với các tệp kiểm soát phiên bản CVS hoặc Subversion nên được bỏ qua. Rốt cuộc, nó chỉ là một kiểm tra đầu. Có lẽ một "xuất khẩu" là phù hợp hơn.


Các bài đăng trước đó sẽ hoạt động hoàn hảo ngoài hộp hoặc với một vài điều chỉnh cho các trường hợp đơn giản, nhưng có một số tình huống bạn có thể muốn tính đến trước khi chạy đổi tên hàng loạt: 1. Điều gì sẽ xảy ra nếu bạn có hai hoặc nhiều tên tại cùng cấp trong hệ thống phân cấp đường dẫn chỉ khác nhau theo từng trường hợp, chẳng hạn như ABCdef, abcDEFaBcDeF? Nên đổi tên kịch bản hủy bỏ hoặc chỉ cảnh báo và tiếp tục? 2. Làm thế nào để bạn xác định chữ thường cho tên không phải US-ASCII? Nếu những cái tên đó có thể xuất hiện, thì nên kiểm tra và loại trừ pass trước? 3. Nếu bạn đang chạy một hoạt động đổi tên
Mihai Limbășan

Câu trả lời:


179

Một phiên bản ngắn gọn bằng cách sử dụng "rename"lệnh:

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

Điều này tránh các vấn đề với các thư mục được đổi tên trước các tệp và cố gắng di chuyển các tệp vào các thư mục không tồn tại (ví dụ: "A/A"vào "a/a").

Hoặc, một phiên bản dài dòng hơn mà không sử dụng "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

Cái sau cho phép linh hoạt hơn với lệnh di chuyển (ví dụ, "svn mv").


36
sử dụng đổi tên có thể được thực hiện theo cách này cũng như đổi tên 'y / AZ / az /' *
Tzury Bar Yochay

3
Coi chừng, cả hai phiên bản sẽ không hoạt động trên một hệ thống tệp không nhạy cảm. Trong trường hợp của tôi, tôi đã thay thế thendòng -encloses bằng (mv "${SRC}" "${DST}.renametmp" && mv "${DST}.renametmp" "${DST}") || echo "${SRC} was not renamed".
Lloeki

6
Cách tiếp cận thứ hai không hoạt động chính xác với tôi với các tệp chứa khoảng trắng (ngữ cảnh: linux, bash).
mờ

4
Sử dụng phiên bản đổi tên cuối cùng, không cần regex. Lệnh đầy đủ trở thành find my_root_dir -depth -exec rename -c {} \;. Thêm -f để đổi tên nếu bạn đang sử dụng hệ thống tệp không phân biệt chữ hoa chữ thường (ví dụ: Mac)
Javache

Điều thứ hai làm việc cho tôi trên Solaris bằng cách loại bỏ các -Ttừ mvlệnh.
Ham

261

Nhỏ hơn tôi vẫn thích:

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

Trong trường hợp các hệ thống tệp không nhạy cảm như HFS + của OS X , bạn sẽ muốn thêm -fcờ:

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

3
linux.icydog.net/rename.php :The renaming utility that comes by default with Ubuntu is a Perl program sometimes called prename
ngủ

1
Cảm ơn, tôi đã sử dụng nó theo cách này $ find | xargs đổi tên 'y / AZ / az /' *
Rashi

5
Điều này giả định rằng bạn đã đổi tên, không phải luôn luôn như vậy. ví dụ về việc đổi tên debian của tôi là hoàn toàn khác
Krzysztof Krasnoyń 17/03/2015

10
Trên Arch, chương trình được gọi perl-rename(và được cung cấp bởi một gói có cùng tên)
jaymmer - Phục hồi Monica

3
Điều này không trả lời cho vấn đề đã cho vì "đổi tên" không được đệ quy.
Cybolic

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

Vui lòng thực hiện "mkdir -p A / B / C" trước khi chạy tập lệnh của bạn.
tzot

2
"Tìm" nên được thay thế bằng bất kỳ lệnh nào bạn sử dụng để lấy danh sách các tệp bạn muốn đổi tên; ví dụ: "ls *. {C, CPP, H}".
JPaget

2
Không hoạt động trên OS X, chỉ in thông tin sử dụng cho find. find .dường như để khắc phục điều này.
emlai

3
Phiên bản "hợp nhất", từ tất cả các nhận xét (câu trả lời không thể chỉnh sửa được nữa):for f in `find .`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
romaricdrigon

1
Ai đó có thể giải thích cho tôi tại sao điều này nên làm việc ở nơi đầu tiên? Nếu nó tìm thấy ./FOO và ./FOO/ebar, trước tiên, nó đổi tên ./FOO thành ./foo, sau đó nó không thể tìm thấy nữa ./FOO/ebar. Nhập câu trả lời của riêng tôi dưới đây sẽ khắc phục điều này.
oisyn

80

Chỉ cần thử những điều sau nếu bạn không cần quan tâm đến hiệu quả.

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

13
Wow, đó là một cách khá kém hiệu quả.
Artjom B.

28
Giả sử rằng hiệu quả tính toán thường KHÔNG phải là vấn đề đáng lo ngại khi bạn thấy mình cần đổi tên các tệp trong một thư mục ... Tôi nghĩ rằng đây có lẽ là giải pháp đơn giản sáng tạo nhất trong chuỗi này. Thực sự một cái gì đó tầm thường này không nên phức tạp như các câu trả lời được chấp nhận chứng minh và cách giải quyết này tỷ lệ thuận hơn nhiều với số lượng suy nghĩ tôi muốn đầu tư vào một hoạt động như thế này. +1000
Peter M. Elias

27
Bạn có thể tăng tốc với công tắc -0(đó là 'không', không nén) , zip -0 -r foo.zip foo/.
Johnny Baloney

3
Tôi đã phải thay đổi hơn 50.000 tên tập tin trong các cấu trúc thư mục khác nhau. Câu trả lời ban đầu được chấp nhận đã thực hiện gần 10% công việc trong 2 phút, trong đó, với việc -0nén, gần như ngay lập tức!
Peon

2
Đây không chỉ là không hiệu quả. Điều này chỉ đơn giản là không thể nếu không có đủ không gian trống cho một kho lưu trữ tạm thời.
Victor Yarema

19

Man, các bạn / các cô gái thích làm phức tạp mọi thứ ... Sử dụng:

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

2
Điều này không hoạt động, nó nói rằng tập tin với tên thấp hơn đã tồn tại.
kirhgoff

@kirhgoff Tôi đã thấy điều đó xảy ra với các mount NFS - làm theo hướng dẫn ở đây .
joebeeson

Làm thế nào chúng ta có thể đổi tên trên một hệ thống tập tin nhạy cảm trường hợp? rename 'y/a-z/A-Z/' /tmp/*.jpg-> Can't rename /tmp/*.jpg /TMP/*.JPG: No such file or directory, tức là cố gắng đổi tên toàn bộ đường dẫn thay vì chỉ tệp.
Pablo A

14

Hầu hết các câu trả lời ở trên đều nguy hiểm, vì chúng không xử lý các tên có chứa các ký tự kỳ lạ. Đặt cược an toàn nhất của bạn cho các loại hình điều là sử dụng find's -print0tùy chọn, trong đó sẽ chấm dứt tên tập tin với ASCII NUL thay vì \ n.

Dưới đây là một kịch bản, trong đó chỉ có file thụ và không tên thư mục để không nhầm lẫ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"'

Tôi đã thử nghiệm nó và nó hoạt động với tên tệp chứa dấu cách, tất cả các loại dấu ngoặc kép, v.v ... Điều này rất quan trọng vì nếu bạn chạy, với quyền root, một trong những tập lệnh khác trên cây bao gồm tệp được tạo bởi

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

... cũng đoán những gì ...


Nó sẽ đơn giản hơn để sử dụng renamethay vì mv.
Victor Yarema

14

Điều này hoạt động nếu bạn đã có hoặc thiết lập lệnh đổi tên (ví dụ: thông qua cài đặt brew trong Mac):

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

9
... nếu bạn thiết lập đổi tên trước, ví dụ: thông quabrew install rename
pduersteler

3
đổi tên 'y / AZ / az /' *
Stephen

4
--lower-case? Đáng buồn thay, đó không phải là trường hợp của Arch Linux.

3
renamekhông phải là một bash dựng sẵn. Nó là một tiện ích bên ngoài và cú pháp sẽ khác nhau tùy thuộc vào phiên bản bạn đã cài đặt. Câu trả lời này không đủ như một giải pháp di động "cho tất cả các hệ điều hành dựa trên unix" như đã tuyên bố.
Corey Goldberg

2
Chỉ cần kiểm tra, renamelệnh được bao gồm trong Fedora mới nhất (28), thông qua util-linux-2.31gói, không có --lower-casetùy chọn.
niXar

11

Điều này hoạt động trên CentOS / Red Hat Linux hoặc các bản phân phối khác mà không có renametập lệnh Perl:

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

Nguồn: Đổi tên tất cả tên tệp từ chữ hoa thành ký tự chữ thường

(Trong một số bản phân phối, renamelệnh mặc định xuất phát từ produc-linux và đó là một công cụ khác, không tương thích.)


Điều này chỉ hoạt động trên một thư mục duy nhất, không đệ quy
Bram

Coool .. Hoạt động tốt
Manikandan Ram

6

Cách tiếp cận đơn giản nhất tôi tìm thấy trên Mac OS X là sử dụng gói đổi tên từ http://plasmasturm.org/code/rename/ :

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

--force Đổi tên ngay cả khi tệp có tên đích đã tồn tại.

--lower-case Chuyển đổi tên tệp thành tất cả chữ thường.

--nows Thay thế tất cả các chuỗi khoảng trắng trong tên tệp bằng các ký tự gạch dưới đơn.


5

Đây là giải pháp tối ưu của tôi, sử dụng tập lệnh shell 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

Tất cả các thư mục đều được đổi tên chính xác và mvkhông đặt câu hỏi khi quyền không khớp và thư mục CVS ​​không được đổi tên (không may các tệp kiểm soát CVS trong thư mục đó vẫn bị đổi tên).

Vì "find -depth" và "find | sort -r" đều trả về danh sách thư mục theo thứ tự có thể sử dụng để đổi tên, tôi thích sử dụng "-depth" cho các thư mục tìm kiếm.


Tìm kiếm đầu tiên của bạn không hoạt động. Hãy thử "mkdir -p A / B / C" và sau đó chạy tập lệnh của bạn.
tzot

4

Câu hỏi ban đầu được yêu cầu bỏ qua các thư mục SVN và CVS, có thể được thực hiện bằng cách thêm -prune vào lệnh find. Ví dụ: bỏ qua CVS:

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

[sửa] Tôi đã thử điều này và nhúng bản dịch chữ thường trong phần tìm kiếm không hoạt động vì những lý do tôi không thực sự hiểu. Vì vậy, sửa đổi điều này thành:

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

Ian


4

Sử dụng trình sửa tên tệp của Larry Wall:

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

Nó đơn giản như

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

( fixtất nhiên là đoạn script ở trên)


3

Đây là một tập lệnh shell nhỏ thực hiện những gì bạn yêu cầu:

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

Lưu ý hành động -depth trong lần tìm đầu tiên.


1
Điều duy nhất hoạt động trên máy Mac từ toàn bộ chuỗi. Cảm ơn đống!
YemSalat

2

Không xách tay, chỉ Zsh, nhưng khá súc tích.

Đầu tiên, đảm bảo zmvđược tải.

autoload -U zmv

Ngoài ra, hãy chắc chắn extendedgloblà trên:

setopt extendedglob

Sau đó sử dụng:

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

Để đệ quy các tệp và thư mục chữ thường trong đó tên không phải là CVS .


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

find -depthin từng tệp và thư mục, với nội dung của thư mục được in trước chính thư mục đó. ${f,,}viết thường tên tập tin.


Điều này không hoạt động: nó đổi tên một thư mục trước khi nó hoạt động trên nội dung, như vậy lần thử sau đó vào nội dung không thành công.
Prune

Thêm -depthbản sửa lỗi đó! Đây là một giải pháp thực sự nhanh chóng, nhưng tất nhiên không cần sử dụng -print0tùy chọn để tìm, nó không đáng tin cậy nhất
jpaugh

@jpaugh Không, không. Nó sẽ cố gắng đổi tên ./FOO/ebar thành ./foo/bar, nhưng ./foo chưa tồn tại vào thời điểm đó.
oisyn

2

Với MacOS,

Cài đặt renamegói,

brew install rename

Sử dụng,

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

Lệnh này tìm tất cả các tệp có *.pyphần mở rộng và chuyển đổi tên tệp thành chữ thường.

`f` - forces a rename

Ví dụ,

$ 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

Tại sao bạn sử dụng -Itùy chọn cho xargsở đây?
Victor Yarema

Các - Ilá cờ là không bắt buộc. Nó được sử dụng khi chúng ta thực thi nhiều lệnh với xargs. Dưới đây là một ví dụ về việc sử dụng nhiều lệnh với xargs cat foo.txt | xargs -I % sh -c 'echo %; mkdir %' Bạn có thể chạy mà không cần -Ilikefind . -iname "*.py" -type f | xargs -I% rename -c -f "%"
akilesh raj

2

Sử dụng typeset :

typeset -l new        # Always lowercase
find $topPoint |      # Not using xargs to make this more readable
  while read old
  do new="$old"       # $new is a lowercase version of $old
     mv "$old" "$new" # Quotes for those annoying embedded spaces
  done

Trên Windows, các mô phỏng, như Git Bash , có thể thất bại vì Windows không phân biệt chữ hoa chữ thường. Đối với những người đó, trước tiên hãy thêm một bước mvlà tệp vào tên khác, như "$ old.tmp", sau đó đến $new.


1

Dài dòng nhưng "Hoạt động không có gì ngạc nhiên & không cần cài đặt"

Kịch bản lệnh này xử lý tên tệp với dấu cách, dấu ngoặc kép, các ký tự khác thường và Unicode, hoạt động trên các hệ thống tệp không nhạy cảm và hầu hết các môi trường Unix-y đã cài đặt bash và awk (gần như tất cả). Nó cũng báo cáo các xung đột nếu có (để lại tên tệp bằng chữ hoa) và tất nhiên đổi tên cả tệp và thư mục và hoạt động theo cách đệ quy. Cuối cùng, nó có khả năng thích ứng cao: bạn có thể điều chỉnh lệnh find để nhắm mục tiêu các tệp / thư mục bạn muốn và bạn có thể điều chỉnh awk để thực hiện các thao tác tên khác. Lưu ý rằng bằng cách "xử lý Unicode" Tôi có nghĩa là nó thực sự sẽ chuyển đổi trường hợp của họ (không bỏ qua chúng như câu trả lời sử dụng 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 {} +

Người giới thiệu

Kịch bản của tôi dựa trên những câu trả lời tuyệt vời này:

/unix/9496/looping-ENC-files-with-spaces-in-the-names

Làm thế nào để chuyển đổi một chuỗi thành chữ thường trong Bash?


1

Điều này cũng hoạt động độc đáo trên macOS:

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

Điều này đặc biệt tốt vì các tàu Ruby có macOS.
jxmorris12

1

Tôi cần phải thực hiện việc này trên thiết lập Cygwin trên Windows 7 và thấy rằng tôi đã gặp lỗi cú pháp với các đề xuất ở trên mà tôi đã thử (mặc dù tôi có thể đã bỏ lỡ một tùy chọn làm việc). Tuy nhiên, giải pháp này trực tiếp từ các diễn đàn Ubuntu hoạt động ngoài khả năng :-)

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

(NB: Trước đây tôi đã thay thế khoảng trắng bằng dấu gạch dưới bằng cách sử dụng:

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

)


1

Trong OS X, mv -fhiển thị lỗi "cùng một tệp", vì vậy tôi đổi tên hai lần:

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

Tôi sẽ tiếp cận Python trong tình huống này, để tránh lạc quan giả định các đường dẫn không có dấu cách hoặc dấu gạch chéo. Tôi cũng thấy rằng python2có xu hướng được cài đặt ở nhiều nơi hơn 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])

Nói về việc làm cho nó phức tạp ... chỉ cần làm .. đổi tên 'y / AZ / az /' *
Stephen

1
@Stephen, giả sử bạn có quyền truy cập quản trị viên để cài đặt đổi tên. Tôi thường xuyên phải chuyển dữ liệu trên các hệ thống mà tôi không có khả năng cài đặt phần mềm khác. Trong Ubuntus gần đây, điều này chỉ được cài đặt nếu có perl.
John Foley

1

Nếu bạn sử dụng Arch Linux , bạn có thể cài đặt rename) gói từ AURđó cung cấp renamexmlệnh dưới dạng /usr/bin/renamexmthực thi và một trang thủ công cùng với nó.

Nó là một công cụ thực sự mạnh mẽ để nhanh chóng đổi tên các tập tin và thư mục.

Chuyển đổi thành chữ thường

rename -l Developers.mp3 # or --lowcase

Chuyển đổi sang trường hợp UPPER

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

Sự lựa chọn khác

-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

Bạn có thể tìm nạp tệp Developers.mp3 mẫu từ đây , nếu cần;)


1
đổi tên từ brewtrên macOS đã -lràng buộc tạo ra một liên kết tượng trưng và -cđể chuyển đổi thành chữ thường, vì vậy hãy coi chừng.
rien333

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

Đầu tiên đổi tên các thư mục từ dưới lên sort -r (trong đó -depth không có sẵn), sau đó là các tệp. Sau đó, grep -v / CVS thay vì tìm ...- cắt tỉa vì nó đơn giản hơn. Đối với các thư mục lớn, đối với f trong ... có thể tràn một số bộ đệm shell. Sử dụng tìm ... | Trong khi đọc để tránh điều đó.

Và vâng, điều này sẽ ghi lại các tập tin chỉ khác nhau trong trường hợp ...


Thứ nhất: find YOURDIR -type d | sort -rlà quá nhiều rắc rối. Bạn muốn find YOURDIR -depth -type d. Thứ hai, find -type fPHẢI chạy sau khi các thư mục đã được đổi tên.
tzot

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

Tôi đã không thử các tập lệnh phức tạp hơn được đề cập ở đây, nhưng không có phiên bản dòng lệnh nào hoạt động cho tôi trên NAS Synology của tôi. renamekhông có sẵn và nhiều biến thể của findlỗi vì dường như dính vào tên cũ của đường dẫn đã được đổi tên (ví dụ: nếu tìm thấy ./FOOtheo sau ./FOO/BAR, đổi tên ./FOOthành ./foovẫn sẽ tiếp tục liệt kê ./FOO/BARmặc dù đường dẫn đó không còn hợp lệ) . Lệnh trên làm việc cho tôi mà không có bất kỳ vấn đề.

Điều gì sau đây là một lời giải thích của từng phần của lệnh:


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

Điều này sẽ tìm thấy bất kỳ tệp nào từ thư mục hiện tại (thay đổi .thành bất kỳ thư mục nào bạn muốn xử lý), bằng cách sử dụng tìm kiếm theo chiều sâu (ví dụ: nó sẽ liệt kê ./foo/bartrước ./foo), nhưng chỉ cho các tệp có chứa ký tự in hoa. Bộ -namelọc chỉ áp dụng cho tên tệp cơ sở, không phải đường dẫn đầy đủ. Vì vậy, điều này sẽ liệt kê ./FOO/BARnhưng không ./FOO/bar. Điều này là ổn, vì chúng tôi không muốn đổi tên ./FOO/bar. Chúng tôi muốn đổi tên ./FOOmặc dù, nhưng cái đó được liệt kê sau này (đây là lý do tại sao -depthquan trọng).

Bản thân comand này đặc biệt hữu ích để tìm các tệp mà bạn muốn đổi tên ở vị trí đầu tiên. Sử dụng lệnh này sau khi đổi tên hoàn chỉnh để tìm kiếm các tệp vẫn chưa được thay thế do va chạm hoặc lỗi tên tệp.


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

Phần này đọc các tệp được xuất ra bởi findvà định dạng chúng trong một mvlệnh bằng cách sử dụng một biểu thức thông thường. Các -ntùy chọn dừng sedtừ in đầu vào, và các plệnh trong việc tìm kiếm và thay thế đầu ra regex văn bản thay thế.

Bản thân regex bao gồm hai hình chụp: phần cho đến phần cuối cùng ((là thư mục của tệp) và chính tên tệp. Thư mục được giữ nguyên, nhưng tên tệp được chuyển thành chữ thường. Vì vậy, nếu findđầu ra ./FOO/BAR, nó sẽ trở thành mv -n -v -T ./FOO/BAR ./FOO/bar. Các -ntùy chọn mvlàm cho chắc chắn hiện file chữ thường không được ghi đè. Các -vtùy chọn làm cho mvđầu ra mọi thay đổi mà nó làm (hoặc không làm - nếu ./FOO/barđã tồn tại, nó sẽ tạo ra một cái gì đó giống như ./FOO/BAR -> ./FOO/BAR, lưu ý rằng không có sự thay đổi đã được thực hiện). Điều -Tnày rất quan trọng ở đây - nó xử lý tệp đích như một thư mục. Điều này sẽ đảm bảo rằng ./FOO/BARnó không được chuyển vào ./FOO/barnếu thư mục đó tồn tại.

Sử dụng điều này cùng với findđể tạo một danh sách các lệnh sẽ được thực thi (tiện dụng để xác minh những gì sẽ được thực hiện mà không thực sự làm điều đó)


sh

Điều này khá tự giải thích. Nó định tuyến tất cả các mvlệnh được tạo đến trình thông dịch shell. Bạn có thể thay thế nó bằng bashhoặc bất kỳ vỏ theo ý thích của bạn.


0

Slugify đổi tên (regex)

Đó không phải là chính xác những gì OP yêu cầu, nhưng những gì tôi đã hy vọng tìm thấy trên trang này:

Phiên bản "slugify" để đổi tên tệp sao cho chúng giống với URL (nghĩa là chỉ bao gồm chữ và số, dấu chấm và dấu gạch ngang):

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

2
"không chính xác"? Đây không phải là tất cả những gì OP yêu cầu
Corey Goldberg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.