web-dev-qa-db-ja.com

すべてのファイル名からアポストロフィを削除する

ディレクトリ内のすべてのファイル名からアポストロフィを削除しようとしました。

for i in *; do mv $i `echo $i | tr -d "'"`; done

このコマンドを実行すると、名前は変更されません。

ここで何が悪いのか知っていますか?

7
xralf

次のようなものを試すことができます(bash):

shopt -s nullglob
for i in *\'* ; do mv -v "$i" "${i/\'/}" ; done

これはシェル文字列置換を使用します。 mvが失敗するため、'が含まれていないファイルをグロブ処理したくない場合があります。 nullglobオプションがない場合、一致するファイルがない場合、グロブパターン自体がmvに渡されます。

8
Mat

常に変数の置換_$foo_とコマンドの置換$(foo)を二重引用符で囲みます(なぜそれらを残す必要があるのか​​わからない場合を除く)アウトして、なぜそうしても大丈夫です)。

_for i in *; do mv "$i" "$(echo "$i" | tr -d "'")"; done
_

これはほとんど機能しますが、いくつかの制限があります。

  • mvはオプションとして解釈するため、ファイル名が_-_で始まる場合、動作が悪くなったりエラーが発生したりします。
  • これは、名前が_._で始まるファイルには影響しません。
  • いくつかの設定では、これはechoコマンドのバックスラッシュを壊します。
  • 名前の最後の改行は失われます。

Ksh93、bash、およびzshでは、_${VARIABLE//PATTERN/REPLACEMENT}_構成を使用して、これをより簡単に記述できます。 _--_をmvに追加すると、_-_で始まるファイル名が処理されます。 _._で始まるファイル名がある場合は、必要に応じて_.*_の後に_.[^.]* ..?*_または_*_を追加します。

_for i in *; do mv -- "$i" "${i//\'/}"; done
_

Zshでは、 zmv を使用できます。

_zmv '(*)' "\${1//\\'/}"
_

Debian、Ubuntu、その他の派生物では、 rename Perlスクリプトを使用できます。

_rename "s/'//g" *
_

あなたの問題は、ファイルの名前にもスペースが含まれていることです。それなしではエラーを再現できません。

$ touch "file" "user's file"
$ for i in *; do mv $i `echo $i | tr -d "'"`; done
mv: `file1' and `file1' are the same file
mv: target `file' is not a directory

したがって、失敗する理由は2番目のメッセージです:target 'file' is not a directory

Forループがスペースのあるファイルを見つけると、次のように実行されます。

mv user's file users file

したがって、3つのファイル(user'sfileusers)、およびこれらのファイルを(file)に移動するディレクトリ。

両方を適切に引用することで、差し迫った問題を解決できます

$ for i in ./*; do mv "$i" "$(echo "$i" | tr -d "'")"; done
3
Mikel