1

私は次のように名前が付けられたたくさんの(700以上の)ディレクトリを持っています

1 - *random*name*1*
2 - *random*name*2*
...
725 - *random*name*725*

先頭の番号(1〜725)は、すべてディレクトリ名の一部です。

つまり、すべてのディレクトリ名は数字で始まり、[スペース][ダッシュ][スペース]、テキストの順に続きます。

次のように名前が付けられるように、名前をまとめて変更したいと思います。

1 - *random*name*725*
2 - *random*name*724*
...
725 - *random*name*1*

ディレクトリ名の数字部分だけを「逆」にしたいのですが。基本的に、「1-」の後に続くテキストは「725-」の後に続き、「2-」の後に続くテキストは「724-」の後に続くようにします。

それを行う最も簡単な方法は何ですか?私はLinuxを使用しています。

注: *ランダム*名*はすべて異なり、説明のみを目的としています。

4

4 に答える 4

1

まず、いくつかのファイル名をシミュレートしましょう。

$ printf 'kjdfh8\nskdjfh9\nckjhv10\naskjdh11\n'
kjdfh8
skdjfh9
ckjhv10
askjdh11

次に、パイプを介して'emを実行します。

$ printf 'kjdfh8\nskdjfh9\nckjhv10\naskjdh11\n' | sed 's/[^0-9]*\(.*\)/\1 &/' | sort -nr | cut -d\  -f2-
askjdh11
ckjhv10
skdjfh9
kjdfh8

これはどのように作動しますか?実はとても簡単です。まず、sed行の先頭に数値コンテンツのコピーを配置するために使用します。次に、並べ替えます。最後にcut、行の先頭の数字を取り除くために使用します。そして、voilà!

さて...それは順序を逆にします。それはあなたの質問の質問の1つですが、あなたの最終目標は物事の名前を変更することです。上記のリストを、whileループでもある別のパイプで拡張できます。今回は読みやすくするためにスペースを空けます。

#!/bin/bash

n=0
printf 'kjdfh8\nskdjfh9\nckjhv10\naskjdh11\n' \
| sed 's/[^0-9]*\(.*\)/\1 &/' | sort -nr | cut -d\  -f2- \
| while read file; do
    base="${file/[0-9]*/}"
    ((n++))
    printf 'mv "%s" "%s%s"\n' "$file" "$base" "$n"
  done

このwhileループは、上記で作成したファイルのリストを読み取ります。ファイル名の最初の桁から始まるすべてのものを削除することにより、「ベース」を取得します。カウンター(新しい名前に使用)をインクリメントmvしてから、古いファイル名、ベース、およびカウンターを使用してコマンドを出力します。

この場合も、このスクリプトの出力はmv、シェルを介してパイプできるコマンドのセットです。

printf明らかに、これをファイルで使用するには、最初のコマンドをファイルのリストを生成するものに置き換える必要があります。

:ファイル名に予期しない文字や特殊文字(スペースも含む)が表示されて計画が破棄されるリスクがあるため、通常、この方法でファイル名を処理することはお勧めできません。あなたがそれを理解していると確信している場合にのみこれを行ってください。

于 2012-07-19T13:58:13.360 に答える
1

を使用する1つの方法perl。コードはコメントされています。

内容script.pl

#!/usr/bin/env perl

use warnings;
use strict;
use File::Basename qw|basename|;

die qq{Usage: perl $0 <real|trial>\n} unless @ARGV == 1;

my $real = $ARGV[0] eq q|real| ? 1 : 0;

## Filter filenames from the directory that match criteria of OP.
my @files = grep { -d $_ && m/\A(\d+)\s-\s.*\1/ } map { basename $_ } <./*>;

## Get numbers in reverse mode to substitute them later in filenames .
my @nums = map { m/\A(\d+)/; $1 || 0 } reverse @files;

## Process all files, change the number of the file and rename it.
for my $file ( @files ) { 
    (my $new_file = $file) =~ s/\A(\d+)/shift @nums/e;

    if ( $real ) { 
        rename $file, $new_file or warn qq|WARN: Couldn't rename "$file"\n|;
    }   
    else {
        printf qq|%s\n|, qq|rename "$file" "$new_file"|;
    }   
}

リストディレクトリ:

ls -1

次の出力で:

1 - file1file
2 - fi2le
3 - fileeee3
4 - fou4r
5 -  donttouch
6 -  donttouch5either
script.pl

スクリプトを実行します。

perl script.pl

ディレクトリを再度リストします。

ls -1

次の出力で:

1 - fou4r
2 - fileeee3
3 - fi2le
4 - file1file
5 -  donttouch
6 -  donttouch5either
script.pl

編集:コメントに実際のトライアルの前にトライアルを実行させるという提案があったので、引数realまたはを追加しましたtrial。最初のオプションでは実際の変更を行い、2番目のオプションではprint実際のコマンドを実行せずに出力します。次に、次のようなスクリプトを実行します。

perl script.pl real

また

perl script.pl trial
于 2012-07-19T13:38:41.807 に答える
0

このawkソリューションがあなたにとって大丈夫なら?

cmd:

ls -F|grep "/$"|sort|awk 'BEGIN{FS=" - ";l=5;}{o=$0;gsub("/$","",o);gsub($1"/$",l--);if(o!=$0)printf "mv \"%s\" \"%s\"\n",o,$0 }' |sh

ここで5はハードコーディングされており、あなたの場合は725になります。:)もちろん、wc -lで設定できますが、私は少し怠惰です。

テスト:

kent$  tree -d
.
|-- 1 - foo1
|-- 2 - foo2
|-- 3 - foo3
|-- 4 - foo4
`-- 5 - foo5

5 directories

#this will only print the generated mv command:

kent$  ls -F|grep "/$"|sort|awk 'BEGIN{FS=" - ";l=5;}{o=$0;gsub("/$","",o);gsub($1"/$",l--);if(o!=$0)printf "mv \"%s\" \"%s\"\n",o,$0 }'   
mv "1 - foo1" "1 - foo5"
mv "2 - foo2" "2 - foo4"
mv "4 - foo4" "4 - foo2"
mv "5 - foo5" "5 - foo1"

# if you pipe the generated command to "sh", they will be executed:

kent$  ls -F|grep "/$"|sort|awk 'BEGIN{FS=" - ";l=5;}{o=$0;gsub("/$","",o);gsub($1"/$",l--);if(o!=$0)printf "mv \"%s\" \"%s\"\n",o,$0 }' |sh


#result:

kent$  tree -d
.
|-- 1 - foo5
|-- 2 - foo4
|-- 3 - foo3
|-- 4 - foo2
`-- 5 - foo1

5 directories
于 2012-07-19T13:53:44.043 に答える
0

これ:

find /path/to/the/directories/location/ -depth -exec mv '{}' $(basename '{}')$(echo $(date "+%H%M%S%N")) \;
于 2013-07-02T09:06:19.200 に答える