現在のディレクトリ内のすべてのファイル(一部の例外を含む)を別のディレクトリにコピーするBashシェルスクリプトを作成しようとしています。スクリプトはコマンドを作成して変数に保存して実行します。混乱した部分は次のとおりです。ビルドされたコマンドがシェルスクリプトで実行されると、「find: paths must precede expression: `|xargs'
前のスペースを削除するとわかります|
」というメッセージで失敗しますfind: unknown predicate `-i'
。しかし、ビルドして実行するように指示するとecho
正しく動作します!もっと奇妙なことは、echo "$cmd"|bash
同じエラーメッセージで失敗することです!
スクリプト( synchronize.sh
):
#! /bin/bash
EXCLUDED_FILES=(folder1 file.txt synchronize.sh)
FLAGS='-r'
PROJECT_NAME=project
TARGET_DIR=$HOME/Documents/IDE/$PROJECT_NAME/assets
cmd='find ./* -maxdepth 0'
cmd_end="|xargs -i cp -r {} -t $TARGET_DIR"
for file in ${EXCLUDED_FILES[@]}
do
cmd+=" ! -name \"$file\""
done
cmd+=$cmd_end
$cmd #Running the command directly fails
#echo $cmd #Yet copying and pasting the output of this command will work just fine
#echo "$cmd"|bash #Though this inexplicably fails, with the same message as just $cmd
ファイルまたはフォルダ名には、スペースや特殊文字(アンダースコアとピリオドを除く)はありません。
答え1
したがって、@KamilMaciorowskiがリンクした回答で、Bashはコマンドが実行される文字列でパイプを異なる方法で処理することに気づきました。配線を変えて問題を解決しましたが、$cmd
今eval "$cmd"
はうまくいきます!
コード挿入の問題が発生する可能性がありますが、eval
これはこの特定のスクリプトとは関係ありません。
答え2
コマンドにリストをロードする方法については良いアイデアがありますが、変数とコマンドを組み合わせるより良い方法があります。
@KamilMaciorowskiはここに良い背景情報を提供しましたが、それでもより確実な答えを探しているかもしれません。ここで詳細を読むと、printf
配列をコマンドとしてフォーマットする良い例がわかります。find
あなたの場合は次のようになります。
find ./* -maxdepth 0 $(printf "! -name %s " $EXCLUDED_FILES) -exec cp -r {} $TARGET_DIR \;