ソートを使用してファイル名内の単語をアルファベット順に並べ替えますか?


8

bashでファイルの名前を一括変更するチュートリアルを読んで、sortコマンドを使用してファイルの内容を並べ替えるとき、2つを組み合わせる方法を理解できませんでした。

プログラムがTagSpacesが物事を処理する方法と同様に、ファイル名内のタグを使用して内容がソートされたディレクトリがあります。ファイル名を作成またはダウンロードするときに、考えられるすべてのタグをファイル名の最後に追加します。次に例を示します。

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

次に、これらすべてのファイルを調べて名前を変更し、タグの前後に影響を与えずにタグをアルファベット順に並べ替えたいと思います(たとえば、画像のタイトルやファイル拡張子)。したがって、上記は次のようになります。

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

どうすればこれを達成できますか?ファイルの内容ではなくファイル名をのようなコマンドに渡す方法を理解することもできませんsort。その出力をパイプで渡すことができmvます。


あなたの質問への答えではありませんが、ファイルへのタグの追加(PDF)に TagSpaceに関する回答を投稿し、コマンドラインまたはスクリプトから処理する必要があります。一見すると、その質問に非常に関連しているようです。
cas

回答:


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

テスト:

##### 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

renameprename一部のシステムでは)perlベースの場合は、perl を使用してタグを分割+ソートできます。たとえば、

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

次に(.jpgサフィックスを削除して置き換えるために醜いラングリングを行います)

$ 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

チェック中

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

おそらく改善の余地はたくさんあります-しかし、それがあなたにいくつかのアイデアを与えることを願っています。


3

zsh

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

-n幸せなら(ドライラン)を削除してください)。

  • [^#]#:0個以上の非#文字(正規表現に#*ています)
  • s: : スペースで分割
  • o:注文(ソート)
  • j: ::スペースと結合します。

したがって、スペースの最初#(含まれている)と最後.(含まれていない)の間の部分を分割し、スペースで結合した結果のリストを並べ替えます。

再帰的に:

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

タグ名にスペースを許可するために#、末尾のスペースを分割してトリムし、ソートして次のように結合できます#

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

(#qD)隠しファイル(Dotファイル)も処理する場合、または隠しディレクトリ内のファイルを処理する場合は、グロブ修飾子を追加します。


2

いい質問だ!

bashこれが私の簡単なスクリプトです。

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

説明:

  • afile=( ${file#*)} );我々は、文字列を配列に変換しています。この状態では、文字列を引用しない限り、シェルはスペースで単語分割を実行しています。

    ${file#*)}カットアップ・ツー・最初のプレフィックス):最初まで私たちは、文字列の先頭からすべてを除去している)使用して見てshell parameter expansion、それはなりますよう#wallpaper #4k #googleimages.jpg考慮しますfile="Sunrise (2) #wallpaper #4k #googleimages.jpg"

  • ${file%%#*}カットアップ・ツー・ラスト・接尾辞)。最後から最後まで#見られるまで、ストリングの始まりから終わりまでストリップを開始します。これは結果になりますSunrise (2)

  • ${afile[@]%%.*}カットアップ・ツー・最後にサフィックス上記と同様、端から最後まで(ここでそれぞれのインデックス配列で)、文字列の懇願に開始ストリッピング:).見られます。これは結果になります#wallpaper #4k #googleimages、私たちは${afile[@]%.*}より良く使うこともできます!

  • ではprintf "%s\n" "${afile[@]%%.*}"、配列要素を改行[@]付きで(インデックス付き配列に使用して)出力します(なぜ改行があるのですか?それらをソートして要素を改行で分割する必要があるため)。

  • では$(sort<(printf "%s\n" "${afile[@]%%.*}")):要素(またはタグ)をソートしています。

  • $(echo $(sort<(printf "%s\n" "${afile[@]%%.*}"))):上記と同じですが、追加のechoコマンドを使用して、並べ替えられた要素を1つの線形に収集しました。

    double xargslike を使用しても同じことが可能... |xargs -n1| sort | xargsです。
    このステップをよりよく理解するには、以下の例を参照してください。

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

最後に、mvコマンドはの名前$fileを変更後の名前に変更します。

Ps:ドライランを終了して実際の名前変更を実行するにecho mv ...は、の前で取り外しmvます。


1

これは、Bashが正直に言うには少し複雑すぎるようです。それは不可能ではありませんが、私の意見では、ここでは「実際の」プログラミング用に作成された言語を使用する方がはるかに良いでしょう。Bashソリューションはおそらくメンテナンス不可能です。(Bashのみのソリューションを侮辱しようとするのではなく、実際には、名前変更マジックはかなり素晴らしいと思います)

とはいえ、Rubyを使用したソリューションを次に示します。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

スクリプトを実行するには、画像が置かれているディレクトリにスクリプトを配置するだけです。このソリューションはC#、問題を引き起こさないような、ばかげた画像名とタグに対してかなり弾力的でなければなりません。ただし、スクリプトを実行する前に必ずバックアップを作成してください。移動操作はと同じように破壊的rmです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.