Bash - 查找带空格的文件并使用sed重命名

时间:2014-01-21 04:33:31

标签: linux bash shell sed find

我一直在尝试编写一个脚本来重命名包含空格的所有文件,并用短划线替换空格。

示例:“Hey Bob.txt”改为“Hey-Bob.txt”

当我使用for循环时,它只是在空格处分割文件名,因此“Hey Bob.txt”给出了单独的参数,如“Hey”和“Bob.txt”。

我尝试了以下脚本,但它一直挂在我身上。

#!/bin/bash
find / -name '* *' -exec mv {} $(echo {} | sed 's/ /-g')\;

3 个答案:

答案 0 :(得分:1)

建立OP的想法:

find ${PATH_TO_FILES} -name '* *' -exec bash -c 'eval $(echo mv -v \"{}\" $(echo {} | sed "s/ /-/g"))' \;
  • 注意:需要指定PATH_TO_FILES变量
编辑:BroSlow指出需要考虑目录结构:

find ${PATH_TO_FILES} -name '* *' -exec bash -c 'DIR=$(dirname "{}" | sed "s/ /-/g" ); BASE=$(basename "{}"); echo mv -v \"$DIR/$BASE\" \"$DIR/$(echo $BASE | sed "s/ /-/g")\"' \; > rename-script.sh ; sh rename-script.sh 

答案 1 :(得分:0)

不是一行,但是避免使用sed,如果你打算将它用于脚本,那么它应该也能正常工作。 (如果要测试,请将mv替换为echo

在bash 4 +

#!/bin/bash
shopt -s globstar
for file in **/*; do
  filename="${file##*/}"
  if [[ -f $file && $filename == *" "* ]]; then
    onespace=$(echo $filename)
    dir="${file%/*}"
    [[ ! -f "$dir/${onespace// /-}" ]] && mv "$file" "$dir/${onespace// /-}" || echo "$dir/${onespace// /-} already exists, so not moving $file" 1>&2 
  fi
done

较旧的bash

#!/bin/bash
find . -type f -print0 | while read -r -d '' file; do
  filename="${file##*/}"
  if [[ -f $file && $filename == *" "* ]]; then
    onespace=$(echo $filename)
    dir="${file%/*}"
    [[ ! -f "$dir/${onespace// /-}" ]] && mv "$file" "$dir/${onespace// /-}" || echo "$dir/${onespace// /-} already exists, so not moving $file" 1>&2 
  fi
done

解释算法

  • **/*以递归方式列出当前目录中的所有文件(**在技术上做到了,但最后添加了/*,因此它不会列出目录本身)
  • ${file##*/}将在文件中搜索*/的最长模式,并将其从字符串中删除。例如/foo/bar/test.txt打印为test.txt
  • $(echo $filename)如果没有引用,则会将空格截断为一个,这样就可以更轻松地替换任意个空格的-
  • ${file%/*}删除最后/之后的所有内容,例如/foo/bar/test.txt打印/foo/bar
  • mv "$file" ${onespace// /-}-替换我们文件名中的每个空格(我们检查先前是否存在经过修补的版本,如果它确实回应了它未能使用stderr,请注意&&之前处理bash中的||
  • find . -type f -print0 | while read -r -d '' file这用于通过设置分隔符而不是处理\
  • 来避免分隔带有空格的字符串

示例输出

$ tree
.
├── bar
│   ├── some dir
│   │   ├── some-name-without-space1.pdf
│   │   ├── some name with space1.pdf
│   ├── some-name-without-space1.pdf
│   ├── some name with space1.pdf
│   └── some-name-with-space1.pdf
└── space.sh
$ ./space.sh
bar/some-name-with-space1.pdf already exists, so not moving bar/some name with space1.pdf
$ tree
.
├── bar
│   ├── some dir
│   │   ├── some-name-without-space1.pdf
│   │   ├── some-name-with-space1.pdf
│   ├── some-name-without-space1.pdf
│   ├── some name with space1.pdf
│   └── some-name-with-space1.pdf
└── space.sh

答案 2 :(得分:0)

另一种方式:

find . -name "* *" -type f |while read file
do
  new=${file// /}
  mv "${file}" $new
done