91887

[code]

    ls
    1.jpeg
    2.jpeg
    3.jpeg
    11.jpeg
    12.jpeg
    13.jpeg
    101.jpeg
    102.jpeg
    103.jpeg
    
[/code]

数字の部分を２増やしたい

[code]

    ls | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'
    1.jpeg 3.jpeg
    101.jpeg 103.jpeg
    102.jpeg 104.jpeg
    103.jpeg 105.jpeg
    11.jpeg 13.jpeg
    12.jpeg 14.jpeg
    13.jpeg 15.jpeg 
    2.jpeg 4.jpeg
    3.jpeg 5.jpeg
    
[/code]

これをxargs -n2 mvに入れると

[code]

     ls | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'| xargs -n2 mv
    ls
    104.jpeg    105.jpeg    14.jpeg     15.jpeg     4.jpeg      5.jpeg
    
[/code]

101.jpeg,11.jpeg,1.jpegが消えてしまいます。

マイナスで試すとうまくいきます。

[code]

    ls | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1-2".jpeg"}'| xargs -n2 mv
    ls
    -1.jpeg     0.jpeg      1.jpeg      10.jpeg     100.jpeg    101.jpeg    11.jpeg     9.jpeg      99.jpeg
    
[/code]

printfでやってみると

[code]

    ls| sed -e s/.jpeg//| awk '{printf ("%d%s %d%s\n",$1,".jpeg",$1+2,".jpeg")}'
    1.jpeg 3.jpeg
    101.jpeg 103.jpeg
    102.jpeg 104.jpeg
    103.jpeg 105.jpeg
    11.jpeg 13.jpeg
    12.jpeg 14.jpeg
    13.jpeg 15.jpeg
    2.jpeg 4.jpeg
    3.jpeg 5.jpeg
    
    ls| sed -e s/.jpeg//| awk '{printf ("%d%s %d%s\n",$1,".jpeg",$1+2,".jpeg")}'| xargs -n2 mv
    ls
    104.jpeg    105.jpeg    14.jpeg     15.jpeg     4.jpeg      5.jpeg
    
    
[/code]

やはり101.jpeg,11.jpeg,1.jpegが消えてしまいます。  
1.jpegから136.jpegで試すと

[code]

    ls
    10.jpeg     100.jpeg    101.jpeg    11.jpeg     137.jpeg    138.jpeg
    
[/code]

8,9,98,99,135,136以外のファイルが消えてしまいます。  
法則性がなんなのかわかりません。  
基礎的な知識がないのでネットで参照させてもらっても解決できずにいます。  
面倒な質問で申し訳ないですがご助力いただければ幸いです。


CC BY-SA 4.0
2022-10-29T06:31:28.813
91886
2022-10-29T09:43:44.653
55096
question
macos command-line zsh shell
ファイル名を111.jpegのように数字で管理していて、xargs -n2 mv で一括で番号を振り直しをしたいのですが、どうしても一部のファイルが消えてしまいます。


### 意図どおりにならない原因

[code]

    ls | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'| xargs -n2 mv
    
[/code]

の場合

mvを実行せず、echoでどんなコマンドを実行しているのか調べてみると、

[code]

    ls | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'| xargs -n2 echo mv
    
[/code]

結果は以下のようになりました。

[code]

    mv 1.jpeg 3.jpeg
    mv 101.jpeg 103.jpeg
    mv 102.jpeg 104.jpeg
    mv 103.jpeg 105.jpeg
    mv 11.jpeg 13.jpeg
    mv 12.jpeg 14.jpeg
    mv 13.jpeg 15.jpeg
    mv 2.jpeg 4.jpeg
    mv 3.jpeg 5.jpeg
    
[/code]

せっかく101.jpegを103.jpegに変えた後に103.jpegを105.jpegに変えています。

### 対処

`ls`の代わりに`ls -r`とすればうまくいきそうです。

[code]

    ls -r | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'| xargs -n 2 echo mv
    
[/code]

結果

[code]

    mv 3.jpeg 5.jpeg
    mv 2.jpeg 4.jpeg
    mv 13.jpeg 15.jpeg
    mv 12.jpeg 14.jpeg
    mv 11.jpeg 13.jpeg
    mv 103.jpeg 105.jpeg
    mv 102.jpeg 104.jpeg
    mv 101.jpeg 103.jpeg
    mv 1.jpeg 3.jpeg
    
[/code]

* * *

【追記】  
lsのソートは辞書順なので、問題があります。  
例えば

[code]

    1.jpeg  101.jpeg  102.jpeg  103.jpeg  11.jpeg  12.jpeg  13.jpeg  2.jpeg  3.jpeg  9.jpeg
    
[/code]

の場合、9.jpegを11.jpegに変更したあと、11.jpegを13.jpegに変更してしまいます。

数値順にソートすればこの問題は回避できそうです。

[code]

    ls -1 | sort -rg | sed s/\.jpeg// | awk '{print $1".jpeg"" " $1+2".jpeg"}'| xargs -n 2 echo mv
    
[/code]

`ls -r`を`ls -1 | sort -rg`に変えて数値順にソートしています。


CC BY-SA 4.0
2022-10-29T07:14:20.770
91887
2022-10-29T09:32:26.337
2022-10-29T09:32:26.337
35558
35558
91886
answer


既に原因は判明していますので、参考までに arithmetic expansion を使う方法を挙げておきます。POSIX complient なので
bash 以外でも有効な機能かと思います(実際、dash でも実行可能です)。

[code]

    $ command ls -1r | while IFS=. read -r a ext;do mv "$a.$ext" "$((a+2)).$ext";done
    
[/code]

**追記**

GNU coreutils に含まれている `ls` コマンドには「数値」順でファイル名をソートするオプションスイッチ(`-v`)があります。

[code]

    $ ls --version
    ls (GNU coreutils) 8.32
    
    $ man ls
    
    -v     natural sort of (version) numbers within text
    
[/code]


CC BY-SA 4.0
2022-10-29T07:42:30.840
91888
2022-10-29T09:43:44.653
2022-10-29T09:43:44.653
47127
47127
91886
answer