次の名前を持つ複数のディレクトリがあります。
再帰的に最後から改行を削除したいと思います。
確認しました繰り返しディレクトリの名前を変更する
私も確認しましたファイル名から改行文字を削除
提案されたソリューションは次のとおりです。
find -name $'*\n*' -exec rename $'s|\n| |g' '{}' \;
しかし、私の場合はfind -name $'*\n*'
何も返されません。削除すると$
ディレクトリを見つけることができます
% find . -name '*\n*'
./second?
% find . -name '*\r*'
./third?
./first?
ただし、実行するとfind . -name '*\n*' -exec rename $'s|\n| |g' '{}' \;
ディレクトリ名は変更されません。find . -name $'*\n*' -exec rename $'\n' ' ' {} \;
私もファイル名から改行文字を繰り返し削除します。。また、ディレクトリ名を変更しませんでした。
どうですか?
答え1
以前もそう言ったじゃない
printf "%q\n" *
プログラムfirst$'\342\200\251' second$'\342\200\251' third$'\342\200\251'
これは$'\342\200\251'
一般的な改行文字ですが、Unicode U+2029 段落区切り記号、UTF-8でエンコードされます。出力には8進バイトがありますe2 80 a9
。
だからfind -name $'*\n*'
マッチしません。ドルがなければ、文字だけが一致するのと同じです-name '*\n*'
。これらのモードは、次の文字を特別にしないようにするシェルグローバルモードにすぎません。たとえば、1つのアスタリスクのみが一致し、すべての項目が一致します。特別なわけではないので、そのままにしておいてください。-name '*n*'
n
second
-name
\
\*
*
n
\n
これで何がわかったので、改行文字を削除したかのように削除できます。 Perlの名前変更を介してFile::Rename
削除する必要があります(たとえば、次を使用)。
find . -depth -name $'*\342\200\251' \
-execdir rename -v $'s|\342\200\251||g' '{}' +
-depth
リーフを持つブランチの前にリーフの名前を変更する必要があります-execdir
(標準ではありませんが一般的です)、rename
名前を変更するにはファイルのデフォルト名のみを使用してファイルを含むディレクトリからリーフを呼び出す必要があります。
... rename -v 's|\342\200\251||g'
Perl 式で Perl なので動作するはずです。するバックスラッシュの解釈も独自にエスケープされます。
持っているコマンドはrename $'s|\n| |g'
空白に置き換えられますが、名前の末尾に文字があるので混乱することもあります。
答え2
そしてzsh
:
autoload zmv # best in ~/.zshrc
zmv -v $'(**/)(*[\n\u2029]*)(#qD)' $'$1${2//[\u2029\n]}'
2つの改行文字(U + 000A)を削除するには、または段落区切り記号文字(U+2029)。
または:
zmv -v $'(**/)(*[[:cntrl:]]*)(#qD)' $'$1${2//[[:cntrl:]]}'
すべての制御文字を削除します。
ただし、U+2029の分類はcntrl
システムによって異なります。 Ubuntu 20.04では動作しますが、FreeBSD 12.2では動作しません。実行[[ $'\u2029' = [[:cntrl:]] ]] && echo yes
してシステムを確認します。