文章を書いていますバッシュスクリプトこれにより、ファイル/ディレクトリが既存のディレクトリパスから別のディレクトリパスに移動されます。ただし、for loop
withステートメントの使用if condition
中に一部の拡張ファイルをスキップすることはできません。私のスクリプトはエラーなしで実行されますが、そこで指定した必要な拡張ファイルをスキップするのではなく、すべてのファイルとif condition
ディレクトリを移動します。以下は私が書こうとしているスクリプトです。
何が間違っているのか教えてください。
私がやろうとしていることは次のとおりです。
#!/bin/env bash
#moving home profile data to another location
echo "Moving Desktop Files"
path=/home/$USER/Desktop/*
for m in $path
do
link=$(basename -s .lnk ${m})
desktop=$(basename -s .desktop ${m})
if [[ "${link}.lnk" == "${m}" ]] || [[ "${desktop}.desktop" == "${m}" ]]
then
echo "skipping link and desktop extension files"
continue
fi
mv -n "$m" /home/$USER/CoreData/HOME/Desktop/
done
答え1
私は非常にバイパス的な方法でファイル名のサフィックスを一致させ、名前にスペースを含むファイルを処理できないようにループを作成しました。
あなたのステートメントに関連する主な問題if
は、$m
パス名にディレクトリパス要素が含まれていること、およびファイル名$desktop
として$link
解釈されるとディレクトリパス要素がないことです。
より安全なコードの推奨事項:
#!/bin/bash
for name in "$HOME/Desktop"/*; do
if [[ $name == *.lnk ]] || [[ $name == *.desktop ]]; then
printf 'Skipping "%s"\n' "$name"
else
mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
fi
done
これは==
内で一致する(ワイルドカード)パターンを使用します。[[ ... ]]
bash
個別に名前のglobbingを実行して変数に保存するには、配列を使用します。
names=( "$HOME/Desktop"/* )
for name in "${names[@]}"; do ... done
上記の引用は、個々のパス名の整合性を維持するために重要です。
または、次のcase ... esac
文を使用してください/bin/sh
。
#!/bin/sh
for name in "$HOME/Desktop"/*; do
case $name in
*.lnk|*.desktop)
printf 'Skipping "%s"\n' "$name"
;;
*)
mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
esac
done
同様に、ワイルドカードを別々に使用しますか?
set -- "$HOME/Desktop"/*
for name do ... done
これは、名前付き配列の代わりに位置パラメータを使用します。シェルはsh
名前付き配列をサポートしません。
または以下を使用してくださいrsync
。
rsync --archive --verbose \
--exclude='*.lnk' \
--exclude='*.desktop' \
"$HOME/Desktop/" "$HOME/CoreData/HOME/Desktop"
(その後、"$HOME/Desktop"
必要に応じて削除)