Bạn có thể làm như thế:
set -C; num=0 ### set -o noclobber; init $num
[ -e "$1" ] && ### this needs to be true
until 2>&3 >"./DUPES/$((num+=1))-$1" && ### try to open() num+=1
mv -- "$1" "./DUPES/$num-$1" ### if opened, mv over it
do :; done 3>/dev/null ### do nothing
Bạn sẽ đảm bảo rằng nhiều trường hợp không thể bảo mật cùng tên cho bất kỳ tệp đã cho nào và tăng biến của bạn.
Các /dev/null
<stderr chỉ giảm khiếu nại của vỏ về một file đã tồn tại khi nó cố gắng để làm sản lượng truncate / chuyển hướng và tìm thấy một mục tiêu hiện có. Trong khi noclobber được bật, nó sẽ không ghi đè lên một tệp khác - nó sẽ chỉ open()
là một tệp mới trừ khi bạn sử dụng >|
. Và vì vậy, bạn không cần khiếu nại vì toàn bộ vấn đề là tăng dần các tệp hiện có cho đến khi tìm thấy tên không tồn tại.
Về khía cạnh hiệu suất - sẽ tốt hơn nếu bạn không bắt đầu từ con số không. Hoặc, nếu bạn đã cố gắng để tạo ra sự khác biệt. Tôi đoán những điều trên có thể được cải thiện phần nào như:
set -C; num=0 ### set -o noclobber; init $num
until 2>&3 >"./DUPES/$((num+=1))-$1" && ### try to open() num+=1
mv -- "$1" "./DUPES/$num-$1" ### if opened, mv over it
do [ -e "./DUPES/$((num*2))-$1" ] && ### halve fail distance
num=$((num*2)) ### up to a point of course
done 3>/dev/null ### done
... nhưng có thể lên tới 1000 bạn không phải lo lắng về điều đó. Tôi đã nhận được tới 65 nghìn tên ngẫu nhiên trong vài giây.
Nhân tiện - bạn có thể nghĩ rằng bạn chỉ có thể:
>"./DUPES/$((num+=1))-$1" mv -- "$1" "./DUPES/$num-$1"
... nhưng nó không hoạt động trong bash
vỏ.
num=0; echo >"/tmp/$((num+=1))" >&2 "$num"; echo "$num" /tmp/[01]
0
1 /tmp/1
Vì bất kỳ lý do gì bash
, việc chuyển nhượng trong một số bối cảnh khác để chuyển hướng - và do đó, việc mở rộng xảy ra theo một thứ tự lạ. Vì vậy, bạn cần một lệnh đơn giản riêng biệt để mở rộng $num
giá trị chính xác khi tôi đến đây &&
. Mặt khác, mặc dù:
num=0; echo "$((num+=1))" "$num"
1 1