如何使用bash脚本replace文件名中的空格

任何人都可以推荐一个安全的解决scheme,从给定的根目录开始recursion地replace文件和目录名下划线的空格? 例如:

$ tree . |-- a dir | `-- file with spaces.txt `-- b dir |-- another file with spaces.txt `-- yet another file with spaces.pdf 

变为:

 $ tree . |-- a_dir | `-- file_with_spaces.txt `-- b_dir |-- another_file_with_spaces.txt `-- yet_another_file_with_spaces.pdf 

使用rename (又名),这是一个可能已经在您的系统上的Perl脚本。 分两步进行:

 find -name "* *" -type d | rename 's/ /_/g' # do the directories first find -name "* *" -type f | rename 's/ /_/g' 

基于Jürgen的答案,并能够使用/usr/bin/rename (Perl脚本)的“Revision 1.5 1998/12/18 16:16:31 rmb1”版本在一个绑定中处理多层文件和目录:

 find /tmp/ -depth -name "* *" -execdir rename 's/ /_/g' "{}" \; 

我用:

 for f in *\ *; do mv "$f" "${f// /_}"; done 

虽然不是recursion的,但它非常快速简单。 我确定这里有人可以更新它是recursion的。

部分“$ {f // / _}”利用bash的参数扩展机制来用参数提供的stringreplace参数中的模式。 相关语法是“$ {parameter / pattern / string}”。 请参阅: https : //www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html或http://wiki.bash-hackers.org/syntax/pe

 find . -depth -name '* *' \ | while IFS= read -rf ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done 

一开始就没有把握,因为我没有想到目录。

你可以使用Doug Harple的detox

 detox -r <folder> 

查找/重命名解决scheme。 重命名是util-linux的一部分。

您需要首先下降深度,因为空白文件名可以是空白目录的一部分:

 find /tmp/ -depth -name "* *" -execdir rename " " "_" "{}" ";" 

你可以使用这个:

  find . -name '* *' | while read fname do new_fname=`echo $fname | tr " " "_"` if [ -e $new_fname ] then echo "File $new_fname already exists. Not replacing $fname" else echo "Creating new file $new_fname to replace $fname" mv "$fname" $new_fname fi done 

bash 4.0

 #!/bin/bash shopt -s globstar for file in **/*\ * do mv "$file" "${file// /_}" done 

下面是一个(非常详细的)find -exec解决scheme,它将“file already exists”警告写入stderr:

 function trspace() { declare dir name bname dname newname replace_char [ $# -lt 1 -o $# -gt 2 ] && { echo "usage: trspace dir char"; return 1; } dir="${1}" replace_char="${2:-_}" find "${dir}" -xdev -depth -name $'*[ \t\r\n\v\f]*' -exec bash -c ' for ((i=1; i<=$#; i++)); do name="${@:i:1}" dname="${name%/*}" bname="${name##*/}" newname="${dname}/${bname//[[:space:]]/${0}}" if [[ -e "${newname}" ]]; then echo "Warning: file already exists: ${newname}" 1>&2 else mv "${name}" "${newname}" fi done ' "${replace_char}" '{}' + } trspace rootdir _ 

这一个更多一点。 我用它来重命名我下载的种子(没有特殊字符(非ASCII),空格,多点等)。

 #!/usr/bin/perl &rena(`find . -type d`); &rena(`find . -type f`); sub rena { ($elems)=@_; @t=split /\n/,$elems; for $e (@t) { $_=$e; # remove ./ of find s/^\.\///; # non ascii transliterate tr [\200-\377][_]; tr [\000-\40][_]; # special characters we do not want in paths s/[ \-\,\;\?\+\'\"\!\[\]\(\)\@\#]/_/g; # multiple dots except for extension while (/\..*\./) { s/\./_/; } # only one _ consecutive s/_+/_/g; next if ($_ eq $e ) or ("./$_" eq $e); print "$e -> $_\n"; rename ($e,$_); } } 

我发现这个脚本,这可能是有趣的:)

  IFS=$'\n';for f in `find .`; do file=$(echo $f | tr [:blank:] '_'); [ -e $f ] && [ ! -e $file ] && mv "$f" $file;done;unset IFS 

这是一个合理大小的bash脚本解决scheme

 #!/bin/bash ( IFS=$'\n' for y in $(ls $1) do mv $1/`echo $y | sed 's/ /\\ /g'` $1/`echo "$y" | sed 's/ /_/g'` done ) 

这只能find当前目录中的文件并重命名它们 。 我有这个别名。

find ./ -name "* *" -type f -d 1 | perl -ple '$file = $_; $file =~ s/\s+/_/g; rename($_, $file);

我只是为了自己的目的。 您可以将其用作参考。

 #!/bin/bash cd /vzwhome/c0cheh1/dev_source/UB_14_8 for file in * do echo $file cd "/vzwhome/c0cheh1/dev_source/UB_14_8/$file/Configuration/$file" echo "==> `pwd`" for subfile in *\ *; do [ -d "$subfile" ] && ( mv "$subfile" "$(echo $subfile | sed -e 's/ /_/g')" ); done ls cd /vzwhome/c0cheh1/dev_source/UB_14_8 done 

对于名为/ files的文件夹中的文件

 for i in `IFS="";find /files -name *\ *` do echo $i done > /tmp/list while read line do mv "$line" `echo $line | sed 's/ /_/g'` done < /tmp/list rm /tmp/list 

对于那些通过使用macOS而苦苦挣扎的人,首先要安装所有的工具:

  brew install tree findutils rename 

然后当需要重命名时,为GNU find(gfind)作为查找的别名,然后运行@Michel Krelin:的行,

 alias find=gfind find . -depth -name '* *' \ | while IFS= read -rf ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done