タイトル名に基づいて任意の名前を使用してMarkdownファイルのバッチの名前を変更し、ターゲット名にスペースを含める必要があります(これは標準です)。私はこの1行を試しています
for i in *;
do mv $i $(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /') ;
done
ただし、名前にスペースが含まれているため、「ターゲットXがディレクトリではありません」というエラーが発生します。
どのようなヒントがありますか?
答え1
主な問題は、コマンド置換が引用されず、異なるパラメータに分割され、各パラメータはパス名拡張の対象となり(後者はありませんbash
)zsh
、mv
2つ以上が見える場合は次のように仮定します。最後はファイルを移動するディレクトリです。
同じ理由でそれ$i
自体を引用し、bash
ダッシュで始まるいくつかのファイル名で発生する問題を回避するには、代わりにパターンに-
inを使用するか、コマンドに閉じるマーカーオプションを入れる必要があります。./*
*
--
mv
また、ファイル名の処理方法を少し簡素化できると思います。まず、sed
複数のコマンドを許可できるので、一度だけ呼び出すだけです。最初の一致だけでなく、すべての一致を置き換えるには、コマンドの/g
最後に追加することもできます。s///
また、バックスラッシュの3つのうち2つは[_\?\!\]
重複します。[_?!]
を一致させるか、バックスラッシュも含めたい場合(一部のユーティリティを使用するとより確実にすることができますが)を使用します_
。?
!
[_\?!]
[_\\?!]
for f in ./*; do
mv -- "$f" "$(grep \# "$f" | head -1 | sed -e 's/# //g' -e 's/[_?!]//g' -e's/[:/]/ - /g')"
done
また、次のようにとgrep
を組み合わせることもできます。head
sed
for f in ./*; do
mv -- "$f" "$(sed -ne '/^# / {s///; s/[_?!]//g; s/[:/]/ - /g; p; q;}' < "$f")"
done
ここで、内部コマンドは{}
パターンによって条件が適用され、/^# /
最後q
にスクリプトがブロックの最後で終了するため、一致する最初の行だけが処理されます。
またawk
:
awk '/^# / { sub(/# /, ""); gsub(/[_?!]/, ""); gsub(/[:/]/, " - "); print; exit }' < "$f"
また、最後の置換をに変更して、s/[:/] */ - /
このような文字列が(ダッシュの後に2つのスペース)の代わりになるようにblah: bleh
することもできます。blah - blah
blah - bleh
答え2
ターゲット名の周りに引用符を追加するだけです。
mv $i "$(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /')" ;