Como substituir os espaços em todos os nomes de arquivos com sublinhado no Linux usando o shell script?

14

Eu tentei seguir o shell script que deve substituir espaços de todos os nomes de arquivos xml

for xml_file in $(find $1 -name "* .xml" -type f);
do
 echo "removing spaces from XML file:" $xml_file
 mv "$xml_file" "${xml_file// /_}";
done

Suponha que eu tenha um arquivo xml com o nome xy z.xml , então ele fornece:

removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat '/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat 'z.xml': No such file or directory
    
por krishna 14.08.2015 / 11:40

3 respostas

22

Use isso com bash :

find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'
find -name "* *" -print0 | sort -rz | \
  while read -d $'
find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'
find -name "* *" -print0 | sort -rz | \
  while read -d $'%pre%' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
' f; do mv -v "$f" "${f// /_}"; done
' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
' f; do mv -v "$f" "${f// /_}"; done

find procurará arquivos com um espaço no nome. Os nomes dos arquivos serão impressos com um nullbyte ( -print0 ) como delimitador para também lidar com nomes de arquivos especiais. Em seguida, o read builtin lê os nomes de arquivos delimitados pelo nullbyte e, finalmente, mv substitui os espaços por um sublinhado.

EDIT: Se você quiser remover os espaços nos diretórios também, é um pouco mais complicado. Os diretórios são renomeados e não mais acessíveis pelo nome find discover. Tente isto:

%pre%

O sort -rz inverte a ordem dos arquivos, para que os arquivos mais profundos de uma pasta sejam os primeiros a serem movidos e a própria pasta seja a última. Portanto, nunca há pastas renomeadas antes que todos os arquivos e pastas sejam renomeados. O comando mv no loop também foi modificado. No nome do destino, apenas removemos os espaços no nome de base do arquivo, senão não seria acessível.

    
por 14.08.2015 / 11:50
14
  1. Usando rename

    find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
    

    ou com $1

    find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
    
  2. Usando mv

    find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
    

    ou com $1

    find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
    
por 14.08.2015 / 11:47
1

Este é um método que encontrei enquanto enfrentava o mesmo problema:

for f in *; do mv "$f" 'echo $f | tr ' ' '_''; done

Eu estava escrevendo um arquivo de script para atualizar automaticamente meus certificados SSL.

    
por 10.09.2018 / 17:21