1つのフォルダにある350個程度のファイル名をランダムに抽出したいのですが、ファイルの元の名前はすべて持ちたいです。つまり、フォルダ内のすべての名前が元の名前からランダムに生成され、新しい名前や欠落している名前がないことを意味します。可能ですか?
(私の質問を明確に説明していない場合は、この質問を自由に編集してください。)
答え1
mkdir aux
ls | shuf > a # a=randomize list of files
(tail -n +2 a ; head -1 a) > b # b=rotate a one line
paste a b > c # c=(name1 name2)*
gawk '{system( "mv " $1 " aux/" $2)}' c # mv name1 -> aux/name2
mv aux/* . # mv aux/name -> name
rm a b
c
必要に応じて回復を続行してください。 (セカンダリファイルの名前を選択してください)
答え2
└-(>:) for i in `seq -w 1 10`; do echo $i > nonce-$i; done
└-(>:) ls
nonce-01 nonce-02 nonce-03 nonce-04 nonce-05 nonce-06 nonce-07 nonce-08 nonce-09 nonce-10
└-(>:) for i in nonce*; do echo $i; cat $i; done
nonce-01
01
nonce-02
02
nonce-03
03
nonce-04
04
nonce-05
05
nonce-06
06
nonce-07
07
nonce-08
08
nonce-09
09
nonce-10
10
└-(>:) ../shuffle test
└-(>:) for i in nonce*; do echo $i; cat $i; done
nonce-01
06
nonce-02
03
nonce-03
04
nonce-04
02
nonce-05
09
nonce-06
10
nonce-07
05
nonce-08
08
nonce-09
07
nonce-10
01
コードは次のとおりです。
#!/bin/bash
[ -z $1 ] && echo 'please submit a target directory' && exit 1
TargetDir=${1}
cd $TargetDir
Sourcearray=( * )
function checkArray
{
for item in ${dest[@]}
do
[[ "$item" == "$1" ]] && return 0 # Exists in dest
done
return 1 # Not found
}
#let's shuffle the array randomly
while [ "${#dest[@]}" -ne "${#Sourcearray[@]}" ]
do
rand=$[ $RANDOM % ${#Sourcearray[@]} ]
checkArray "${Sourcearray[$rand]}" || dest=(${dest[@]} "${Sourcearray[$rand]}")
done
let i=0
#let mv the source file to dest file name
while [[ "${i}" -ne "${#dest[@]}" ]] ; do
mv ${Sourcearray[$i]} tmp-${dest[$i]}
let i=$i+1
done
# and rename to go back to the original name
rename 's/tmp-//' *
答え3
アイデアは次のとおりです。
- 元の名前のリストを取得します。救う。
- リストのスクランブルバージョンを保存します(
sort -R
)。 - たとえば、各名前に何かを追加するなど、競合しないように元のリストを削除します。
- 破損したリストを順番に反映するように元のファイルを移動します。
- 混在した元のリストを反映するように破損したファイルを移動します。
デフォルトのシェルコードでは、ファイル名に改行がないと仮定すると、現在のディレクトリはシャッフルの宛先ディレクトリであり、外部ディレクトリは書き込み可能です。
find . -type f > ../list
< list sort -R > ../shuffled
while read f; do mv "$f" "$f".tmp; done < ../list
exec 3<../shuffled
while read f; do read s <&3; mv "$f".tmp "$s"; done < ../list
exec 3>&-
答え4
これを行うためのよく知られたコマンドはありませんが、幸いなことに、シェルインタプリタはこの操作と同様の操作を非常に簡単に実行できます。たとえば、
for i in /my/this/dir/*;do mv -vf "$i" "$i.$RANDOM";done
/my/this/dir
ディレクトリ内のファイルは段階的に実行され、mv
名前に0から32767の乱数を追加する(名前変更)コマンドが実行されます。たとえば、ディレクトリでこのコマンドを実行すると、/sbin
そのディレクトリのファイル名が次のように変更されます。
ifconfig -> ifconfig.4553
ip -> ip.12767
...
/ sbinではこれを実行しないでください。システムがシャットダウンします!(しかし面白いと思います:-))
しかし、あなたが望むものではない場合、復元するのは難しいかもしれません。したがって、このスクリプトを実行する前にmv
プレフィックスを追加してテストできますecho
。
for i in /my/this/dir/*;do echo mv -vf "$i" "$i.$RANDOM";done
2番目の1行スクリプトは何もしませmv
んecho
。