1

dotfiles リポジトリをホーム ディレクトリに同期するためのシェル スクリプトを作成しました。これは Cygwin (zsh) では正常に動作していましたが、Linux (Xubuntu 12.10 の zsh) に移行したばかりで失敗しています。

スクリプトは、リポジトリ内の関連するドットファイルのリストを作成し、シンボリック リンクを作成する前に、衝突をアーカイブします。アーカイブ ルーチンは次のとおりです。

for i in $dotFiles; do
  toArchive=$toArchive $(ls -d $i)
done

$dotfilesのアイテムが存在しない場合、これは失敗します。ls戻りNo such file or directory、スクリプトは終了します。

これを解決するためにリダイレクトstderrしますか? /dev/nullすなわち:

for i in $dotFiles; do
  toArchive=$toArchive $(ls -d $i 2>/dev/null)
done

...またはより良い解決策はありますか?

(完全を期すために、私のスクリプトはhereです。)

4

4 に答える 4

2

シェルスクリプトで最悪なのは、それを機能させることです。2番目に悪いのは維持です(各ライン/オプションが何をしたかを6か月以内に把握しなければなりません)。それを念頭に置いて、存在チェックを追加することをお勧めします。

for i in $dotFiles; do
  if [[ -e $i ]]; then
      toArchive=$toArchive $(ls -d $i)
  fi
done
于 2012-12-11T09:56:25.040 に答える
1

Zshは、他のシェルとは異なり、ファイル名のパターンが何にも一致しない場合、コマンドを実行しません。空のディレクトリにあるという意味はecho hello *、実際hello *には画面に印刷されません。代わりに、zshは上記のエラーメッセージを出力し、echo実行されません。

NOMATCHデフォルトでアクティブになっていると呼ばれるファンキーなオプションの1つを使用して、オンとオフを切り替えることができます。それがどのように機能するかについてのzshの情報ページを読んでください。また、zshFAQの第2章でもこれについて説明しています。

ただし、私があなたの意図を正しく解釈すると、実際に存在する場合と存在しない場合があるファイル名のリストがあり、ファイル名が存在する場合にのみバックアップに含める必要があります。その場合は、配列とファイル存在テストを使用したより良いバージョンがあります。

typeset -a files_to_backup
for file in $dotFiles ; do
  if [[ -f $file ]] files_to_backup=($files_to_backup $file)
done

ifこれは、疑問に思っている場合に備えて、zshの短い条件付き構文も使用します。

于 2012-12-11T08:14:32.273 に答える
1

スクリプトが最初のエラーで終了した理由が正確にはわかりません (set -e実際には? Makefile ルールの一部として実行されていますか?)。

 cmd || :

(読み取り: command または true )。する

  $(ls -d $i || :)

トリックをしますか?

PS: あなたのスクリプトを見ました。実際、set -e有効です。完全に削除するか、スクリプトの特定の領域に対してのみ選択的にオンにすることができます (set +eの効果を元に戻しますset -e)。

于 2012-12-10T10:38:43.073 に答える
0

ここに投稿された提案を個別に取り上げ、それらをソリューション全体にまとめました。何が原因でスクリプトのロジックが壊れていたのかはわかりませんが、推測すると、おそらくlszsh 配列ではなく、間隔を空けた文字列の結果を解析したり、使用したりしていたと思います..とにかく、作業スクリプトは次のとおりです。

#!/bin/zsh

# Break on first error and unset variables
set -e
set -u

# Gather dotfiles
repoDir=$(pwd)

cd $repoDir/public
publicDotfiles=(.*)
cd $repoDir/private
privateDotfiles=(.*)

# Determine clashes, to backup
typeset -a toBackup
for file in $publicDotfiles $privateDotfiles; do
  dotFile=$HOME/$file
  if [[ -e $dotFile ]] toBackup=($toBackup $dotFile)
done

if [[ "$toBackup" != "" ]]; then
  backupFile=$HOME/dotfiles.$(date +%Y%m%d).tar.gz
  tar czPf $backupFile $toBackup --remove-files
fi

# Create symlinks
for i in $publicDotfiles; do
  ln -s $repoDir/public/$i $HOME/$i
done

for i in $privateDotfiles; do
  ln -s $repoDir/private/$i $HOME/$i
done

私がそれをしている間、私はそれをもう少し堅牢にしました:

  • ドットファイルには、パブリックとプライベートの 2 つのクラスがあります。プライベート ディレクトリは.gnupgなどのもの用です。その内容は Git によって無視されるため、プッシュされることはありません。
  • スクリプトが独自のディレクトリから実行される場合、プロジェクト フォルダーはどこにでも置くことができ、スクリプトは絶対パスを計算します。
于 2012-12-11T22:42:29.863 に答える