Bảng chữ cái từ trong tên tập tin bằng cách sử dụng sắp xếp?


8

Khi đọc hướng dẫn về đổi tên hàng loạt trong bash và sử dụng sortlệnh để sắp xếp nội dung tệp, tôi không thể tìm ra cách kết hợp cả hai.

Tôi có một thư mục có nội dung được sắp xếp bằng các thẻ trong tên tệp, tương tự như cách chương trình TagSpaces xử lý mọi thứ. Tôi thêm bất kỳ thẻ nào tôi có thể nghĩ đến cuối tên tệp khi tôi tạo hoặc tải xuống. Đây là một ví dụ:

Sunrise (2) #wallpaper #4k #googleimages.jpg

Bây giờ tôi muốn duyệt qua tất cả các tệp này và đổi tên chúng để các thẻ được sắp xếp theo thứ tự bảng chữ cái, mà không ảnh hưởng đến bất kỳ thứ gì trước hoặc sau các thẻ (ví dụ: tiêu đề của hình ảnh hoặc phần mở rộng tệp). Vì vậy, những điều trên sẽ trở thành:

Sunrise (2) #4k #googleimages #wallpaper.jpg

Làm thế nào để tôi thực hiện điều này? Tôi thậm chí không thể tìm ra cách chuyển tên tệp , chứ không phải nội dung của nó, cho một lệnh như sort, mà đầu ra mà sau đó tôi có thể chuyển sang mv.


không phải là câu trả lời cho câu hỏi của bạn, nhưng bạn nên đăng câu trả lời về TagSpaces trong Thêm thẻ vào tệp (PDF) và xử lý từ dòng lệnh hoặc tập lệnh - thoạt nhìn có vẻ rất phù hợp với câu hỏi đó.
cas

Câu trả lời:


5
#!/bin/bash

for i in dir_for_files/*; do
    filename=${i%%#*}
    sorted_tags=$(grep -o "#[^ .]*" <<< "$i" | sort -n | tr '\n' ' ')
    ext=${i#*.}
    echo mv "$i" "${filename}${sorted_tags% }.$ext"
done

Kiểm tra:

##### Before sorting #####    
$ ls -1 dir_for_files
Note (3) #textfile #notes #important.txt
Sunrise (2) #wallpaper #4k #googleimages.jpg
Sunset (2) #wallpaper #2k #images.jpg

$ ./sort_tags.sh

##### After sorting #####
$ ls -1 dir_for_files
Note (3) #important #notes #textfile.txt
Sunrise (2) #4k #googleimages #wallpaper.jpg
Sunset (2) #2k #images #wallpaper.jpg

3

Nếu bạn có perl dựa trên rename( prenametrên một số hệ thống) thì bạn có thể thực hiện phân tách + sắp xếp các thẻ bằng perl. Ví dụ, được đưa ra

$ ls *.jpg
Sunrise (2) #wallpaper #4k #googleimages.jpg

sau đó (với một số thay đổi xấu xí để loại bỏ và thay thế .jpghậu tố)

$ rename -v 'my @F = split / #/, substr($_,0,-4); $_ = (join " #", shift @F, sort @F) . ".jpg"' *.jpg
Sunrise (2) #wallpaper #4k #googleimages.jpg renamed as Sunrise (2) #4k #googleimages #wallpaper.jpg

Kiểm tra

$ ls *.jpg
Sunrise (2) #4k #googleimages #wallpaper.jpg

Có lẽ rất nhiều chỗ để cải thiện - nhưng tôi hy vọng nó mang lại cho bạn một số ý tưởng.


3

Với zsh:

autoload zmv # best in ~/.zshrc
zmv -n '([^#]#)(\#*)(.*)' '$1${(j: :)${(os: :)2}}$3'

(loại bỏ -n(chạy khô) nếu hạnh phúc).

  • [^#]#: 0 hoặc nhiều ký tự không # ( #giống như *trong biểu thức chính quy)
  • s: : phân chia trên không gian
  • o: thứ tự (sắp xếp)
  • j: :: tham gia với không gian.

Vì vậy, chúng tôi sẽ phân chia phần ở giữa phần đầu tiên #(bao gồm) và phần cuối .(loại trừ) trên không gian, sắp xếp danh sách kết quả mà chúng tôi kết hợp lại với không gian.

Đệ quy:

zmv -n '(**/)([^#]#)(\#*)(.*)' '$1$2${(j: :)${(os: :)3}}$4'

Để cho phép khoảng trắng trong tên thẻ, chúng ta có thể tách #và cắt các khoảng trắng ở cuối, sắp xếp và nối #với:

zmv -n '([^#]#\#)(*)(.*)' '$1${(j: #:)${(os:#:)2}%% #}$3'

Thêm một (#qD)vòng loại toàn cầu nếu bạn cũng muốn xử lý các tệp ẩn ( Dtệp ot) hoặc muốn xử lý tệp trong các thư mục ẩn.


2

Câu hỏi hay!

Đây là bashkịch bản đơn giản của tôi cho việc này:

for file in *.jpg; do 
    afile=( ${file#*)} ); 
    echo mv "$file" "${file%%#*}$(echo $(sort<(printf "%s\n" "${afile[@]%%.*}"))).jpg";
done

Giải trình:

  • Trong afile=( ${file#*)} );: chúng tôi đang chuyển đổi chuỗi thành một mảng. Trong vỏ trạng thái này đang thực hiện phân tách từ với khoảng trắng trừ khi bạn trích dẫn chuỗi.

    Trong ${file#*)}( cut-up-to-First-prefix ): chúng tôi đang tước mọi thứ từ đầu chuỗi cho đến lần đầu tiên )nhìn thấy bằng cách sử dụng shell parameter expansionvì nó sẽ dẫn đến #wallpaper #4k #googleimages.jpgviệc xem xétfile="Sunrise (2) #wallpaper #4k #googleimages.jpg"

  • Trong ${file%%#*}( cut-up-to-last-hậu tố ); tước bắt đầu từ cuối đến cầu xin chuỗi cho đến lần cuối #nhìn thấy. điều này sẽ dẫn đếnSunrise (2)

  • Trong ${afile[@]%%.*}( cut-up-to-last-hậu tố ): giống như trên, tước bắt đầu từ đầu đến cuối chuỗi (ở đây trong mỗi mảng được lập chỉ mục) cho đến lần cuối .nhìn thấy. Điều này sẽ dẫn đến #wallpaper #4k #googleimages, chúng tôi cũng có thể sử dụng ${afile[@]%.*}tốt hơn!

  • Trong printf "%s\n" "${afile[@]%%.*}": chúng tôi đang in các phần tử mảng bằng dòng mới ( [@]được sử dụng cho mảng được lập chỉ mục), (tại sao với dòng mới? Bởi vì chúng tôi sẽ sắp xếp chúng và chúng tôi nên chia các phần tử trong dòng mới)

  • Trong $(sort<(printf "%s\n" "${afile[@]%%.*}")): chúng tôi đang sắp xếp các yếu tố (hoặc thẻ).

  • Trong $(echo $(sort<(printf "%s\n" "${afile[@]%%.*}"))): giống như trên nhưng chúng tôi đã sử dụng echolệnh bổ sung để tập hợp các phần tử được sắp xếp vào một tuyến tính.

    có thể tương tự với việc sử dụng gấp đôi xargsnhư thế ... |xargs -n1| sort | xargs.
    Vui lòng xem ví dụ dưới đây để hiểu rõ hơn về bước này:

    echo -e "C\n4\nB" |sort
    4
    B
    C
    echo $(echo -e "C\n4\nB" |sort)
    4 B C

Cuối cùng, khi kết thúc, mvlệnh sẽ đổi tên thành tên $fileđã sửa đổi.

Ps: loại bỏ echo mv ...ở phía trước mvđể thoát khô và thực hiện đổi tên thực tế.


1

Điều này có vẻ hơi phức tạp đối với Bash để thành thật. Điều đó không phải là không thể, nhưng theo tôi, bạn tốt hơn hết là sử dụng một ngôn ngữ dành cho lập trình "thực" ở đây. Một giải pháp Bash có thể sẽ không thể thay đổi. (Không cố gắng lăng mạ giải pháp chỉ dành cho Bash, tôi nghĩ rằng ma thuật đổi tên là khá tuyệt vời, thực sự)

Điều đó nói rằng, đây là một giải pháp với Ruby. Bạn có thể ghi nó vào một tệp và sau đó chỉ cần thực thi tệp từ trong shell của bạn, với điều kiện bạn đã cài đặt Ruby.

#!/usr/bin/env ruby
Dir.glob('*.jpg').each do |filename|
    # `name` contains the name of the file, without the tags. `tags` is an array
    # of all tags of the file.
    name, *tags = filename.split(' #')
    # if there aren't any tags, just skip the file.
    if tags.empty?
        next
    end
    # remove the trailing '.jpg' and sort all the tags
    tags.last.gsub!(/\.jpg$/,'')
    tags.sort!
    tags = [name] + tags
    # finally, move the file to the correct location with sorted tags.
    File.rename filename, "#{tags.join(' #')}.jpg"
end

Để thực thi tập lệnh, chỉ cần đặt nó vào thư mục chứa hình ảnh của bạn. Giải pháp này khá linh hoạt với các tên và thẻ hình ảnh ngớ ngẩn như C#sẽ không gây ra vấn đề. Điều đó nói rằng, hãy chắc chắn để tạo một bản sao lưu trước khi chạy tập lệnh. Hoạt động di chuyển có thể chỉ là phá hoại như a rm.

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.