O uso de -exec do find deve funcionar, embora seja recursivo por meio de subdiretórios, o que, por sua vez, falhará se algum dos subdiretórios contiver :
ou ?
.
find . -name "*[:?]*" -exec rename 'y/:?/__/' {} +
O erro argument list too long
que você obtém porque o *
é expandido para todos os 160k arquivos no diretório, o que excede o tamanho máximo do argumento em seu sistema.
$ getconf ARG_MAX
2097152
160k nomes de arquivos podem facilmente exceder 2 MiB. Você pode trabalhar além disso renomeando um arquivo de cada vez
for file in ./*[:?]*; do
mv "$file" "${file//[:?]/_}"
done
ou preencha uma matriz e processe-os em blocos. O tamanho da parte do bloco depende do comprimento médio dos nomes de arquivos e do valor de ARG_MAX; ou apenas definir um valor baixo o suficiente para ser seguro, por ex. 1000:
files=( ./*[:?]* ) n=${#files[@]}
size=1000
for (( i=0; i<n; i+=size )); do
rename 'y/:?/__/' "${files[@]:i:size}"
done
Veja também BashFAQ 30 .