web-dev-qa-db-ja.com

bashスクリプトを使用してファイル名の中のスペースを置き換える方法

誰かが与えられたルートディレクトリから始まるファイルとディレクトリ名のアンダースコアでスペースを再帰的に置き換える安全な解決策を推薦できますか?例えば:

$ 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
231
armandino

rename(別名prename)を使用してください。これは、あなたのシステムにすでに存在している可能性があるPerlスクリプトです。 2つのステップでそれをしてください:

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

Jürgen'sに基づき、 "Revision 1.5 1998/12/18 16:16:31 rmb1"バージョンの/usr/bin/rename(Perlスクリプト)を使用して単一の範囲内でファイルとディレクトリの複数の層を処理することができる:

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

私が使う:

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

再帰的ではありませんが、非常に高速で簡単です。私はここの誰かが再帰的にそれを更新することができると確信しています。

${f// /_}パートは、bashのパラメータ展開メカニズムを利用して、パラメータ内のパターンを提供された文字列に置き換えます。関連する構文は${parameter/pattern/string}です。参照してください: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html または http://wiki.bash-hackers.org)/syntax/pe .

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

私はディレクトリを考えていなかったので、最初は正しく理解できませんでした。

doug Harpleによるdetoxを使うことができます

detox -r <folder>
25
user78274

A 検索/名前変更解決策。 名前の変更はutil-linuxの一部です。

空白のファイル名は空白のディレクトリの一部になることがあるので、最初に深さを下げる必要があります。

find /tmp/ -depth -name "* *" -execdir rename " " "_" "{}" ";"
11
Jürgen Hötzel

あなたはこれを使用することができます:

    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
5
Itamar

バッシュ4.0

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

これはもう少しします。ダウンロードしたトレントの名前を変更するために使用します(特殊文字(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,$_);
    }
}
2
degi

これは "file already exists"という警告をstderrに書き込む(非常に冗長な)find -execソリューションです。

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 _
2
yabt

私はこのスクリプトのまわりで見つけました、それは面白いかもしれません:)

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

Naidim's Answersの再帰バージョン。

find . -name "* *" | awk '{ print length, $0 }' | sort -nr -s | cut -d" " -f2- | while read f; do base=$(basename "$f"); newbase="${base// /_}"; mv "$(dirname "$f")/$(basename "$f")" "$(dirname "$f")/$newbase"; done
1
Junyeop Lee

これは、適度な大きさのbashスクリプトソリューションです。

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

私は自分の目的のためだけに作っています。あなたはそれを参照として使うことができます。

#!/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
0
Hongtao

/ 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
0

macOSを使ってこれに苦しんでいる人たちのために、まずすべてのツールをインストールしてください:

 brew install tree findutils rename

それから、名前を変更する必要があるときは、GNU find(gfind)のエイリアスをfindとして作成し、@ Michel Krelin:の行を実行します。

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

これだけ--- カレントディレクトリ内のファイルを見つけて名前を変更する。これにエイリアスがあります。

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

0
user1060059