Peringatan: Saya mengetik sebagian besar perintah ini langsung di browser saya. Lektor peringatan.
Dengan zsh dan zmv :
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
Penjelasan: Pola ini **/*
cocok dengan semua file di subdirektori dari direktori saat ini, secara rekursif (tidak cocok dengan file di direktori saat ini, tetapi ini tidak perlu diganti namanya). Dua pasang kurung pertama adalah grup yang dapat disebut sebagai $1
dan $2
dalam teks pengganti. Pasangan terakhir kurung menambahkan D
kualifikasi glob sehingga file dot tidak dihilangkan. -o -i
artinya meneruskan -i
opsi ke mv
sehingga Anda diminta jika file yang ada akan ditimpa.
Dengan hanya alat POSIX:
find . -depth -exec sh -c '
for source; do
case $source in ./*/*)
target="$(printf %sz "${source#./}" | tr / -)";
mv -i -- "$source" "${target%z}";;
esac
done
' _ {} +
Penjelasan: case
pernyataan menghilangkan direktori saat ini dan subdirektori tingkat atas dari direktori saat ini. target
berisi nama file sumber ( $0
) dengan ./
strip utama dan semua garis miring diganti dengan tanda hubung, ditambah final z
. Final z
ada di sana dalam kasus nama file berakhir dengan baris baru: jika tidak, substitusi perintah akan menghapusnya.
Jika Anda find
tidak mendukung -exec … +
(OpenBSD, saya melihat Anda):
find . -depth -exec sh -c '
case $0 in ./*/*)
target="$(printf %sz "${0#./}" | tr / -)";
mv -i -- "$0" "${target%z}";;
esac
' {} \;
Dengan bash (atau ksh93), Anda tidak perlu memanggil perintah eksternal untuk mengganti garis miring dengan tanda hubung, Anda dapat menggunakan ekspansi parameter ksh93 dengan konstruksi penggantian string ${VAR//STRING/REPLACEMENT}
:
find . -depth -exec bash -c '
for source; do
case $source in ./*/*)
source=${source#./}
target="${source//\//-}";
mv -i -- "$source" "$target";;
esac
done
' _ {} +