echo、xargs、およびcpを使用して、1つのファイルの出力を複数のファイルにコピーしようとしています。私の問題は、xargsが配列の最初のファイルにのみ印刷し、3つのファイルすべてのコピーに印刷しないことです。 xargsを誤って使用しているか、構文が正しくありません。私は数日間これをやってきましたが、これまでいくつかのGoogleページでは運がありませんでした。どんな助けでも大変感謝します!
#!/bin/bash
NF1=/home/user3/mynewfile
U3=/home/user3/
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests/,grades/},MyStuff/{Tests/,Labs/},NOS/};
echo /etc/hosts.allow > $NF1;
echo $U3/CIT/tests/${File[*]} $U3/CIT/grades/${File[2]} | xargs -n 1 cp $NF1
答え1
構文に関連があると思われる場合は、他の問題も発見され、使用を完全に捨ててループをxargs
好むバージョンを思い出しましたfor
。
#!/bin/bash
U3=/home/user3/
NF1=/home/user3/mynewfile
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests,grades},MyStuff/{Tests,Labs},NOS};
echo /etc/hosts.allow > $NF1;
for i in "${File[@]}"; do
cp $NF1 $U3/$i
done
cp $NF1 $U3/CIT/grades/${File[2]}
mkdir
不要な末尾のスラッシュを削除するために行が簡素化され、mkdir
後続のスラッシュの有無にかかわらずディレクトリをアクティブにするので、入力は不要です。
残りの変更理由:
重複スラッシュ
元のコードを数行最初にテストする場合:
$ U3=/home/user3/
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/grades/${File[2]}
/home/user3//CIT/grades/mynewfile1
保存されたパスには$U3
末尾のスラッシュが設定されており、その行の $U3/CIT/grades/${File[2]}
後にもスラッシュがあり、$U3
bashがそれに拡張します。これは、二重スラッシュがたとえば文句を言うことができるものと同じではない/home/user3//CIT/grades/mynewfile1
ため、問題になります。//
/
cp
no such file or directory
したがって、単一のスラッシュを参照する場合は、最初に末尾のスラッシュなしで/
設定することをお勧めします。$U3
$ U3=/home/user3
$ File=(grades mynewfile mynewfile1 mynewfile2)
$ echo $U3/CIT/tests/${File[2]}
/home/user3/CIT/tests/mynewfile1
これで、追加のスラッシュなしで正しいパスが作成されます。
無効なサポート拡張
修正後の次のエラーは次のとおりです。
$ echo $U3/CIT/tests/${File[*]}
/home/user3/CIT/tests/grades mynewfile mynewfile1 mynewfile2
私は、コンマを使用した中括弧拡張などの一般的な接頭辞をFile
使用して配列のファイル名を拡張しようとしていると思います。/home/user3/CIT/tests
$ echo tweedle{dum,dee}
tweedledum tweedledee
このタイプの支柱の拡張では、
- 中かっこの直前
{
、後ろ、}
または両方に文字列を正しく適用したものです。 - ただし
word
、コンマを使用して他の単語などを使用します。,
- しかし、あなたは置いた
${File[*]}
。配列の内容をこのように扱うのを見たことはありません。
$U3
代わりに、同じ共通の開始単語または文字列()と配列()に応じて異なる部分からなるリストを出力するには、ループを使用することをお勧め$File
します。for
$ for i in "${File[@]}"; do
> echo $U3/$i
> done
入力する必要はなく、>
bashは行の連続を示すために自動的に提供されます。スクリプトは次のことを行います。
for i in "${File[@]}"; do
echo $U3/$i
done
結果はいつも
/home/user3/grades
/home/user3/mynewfile
/home/user3/mynewfile1
/home/user3/mynewfile2
- の引用符()と
for i in "${File[@]}"; do
プラスは、"
ループが配列内の各ファイル名を別々の引数として正しく理解できるようにするために@
重要です。for
$File
テスト
最後の目標は、変数が参照する単一のファイルをplus配列plus$NF1
の拡張として定義された複数の場所にコピーすることです。$U3
$File
$U3/CIT/tests/${File[2]}
この場合、最良の方法は、echoと実行したいコマンドを使用してテストすることです。cp
したがって、set
まずテストを実行しましょう。
$ NF1=/home/user3/mynewfile
それから
$ for i in "${File[@]}"; do
> echo cp $NF1 $U3/$i
> done
cp /home/user3/mynewfile /home/user3/grades
cp /home/user3/mynewfile /home/user3/mynewfile
cp /home/user3/mynewfile /home/user3/mynewfile1
cp /home/user3/mynewfile /home/user3/mynewfile2
$U3/CIT/grades/${File[2]}
また、忘れないようにコピーしたいようですので、追加の行として追加してください。
$ echo cp $NF1 $U3/CIT/grades/${File[2]}
cp /home/user3/mynewfile /home/user3/CIT/grades/mynewfile1
- これはすべて
cp
実行されるコマンドに対応します。 xargs
元のコードと同様の方法でパラメータを使用するように書き換えることができますが、実際にはより多くの入力が必要なので、これを避けます。
echo
したがって、この記事の例のエントリを削除してコードの最終バージョンを生成してください。
答え2
私が書いたスクリプトに何が問題なのかわかりません。 don_crisstiが指摘したように、set -x
スクリプトとして使用される2番目の行はデバッグのための良い開始点です。問題が何であるかを一目で確認するのに十分なxargsと配列の拡張について十分に知りません。
しかし、、簡単な回避策があります。この問題を解決するより良い方法とにかく:を使用すると、tee
1つのコマンドで複数のファイルに書き込むことができ、必要に応じてファイルの内容を置き換える代わりにテキストを追加することもできます。
スクリプトを正しく読んだら、必要なものは次のとおりです。
#!/bin/bash
NF1=/home/user3/mynewfile
U3=/home/user3/
File=(grades mynewfile mynewfile1 mynewfile2)
mkdir -p /home/user3/{CIT/{tests/,grades/},MyStuff/{Tests/,Labs/},NOS/};
cd ${U3}CIT/tests/
echo /etc/hosts.allow | tee ${File[*]} ${U3}CIT/grades/${File[2]} $NF1
cd -
cd
編集:配列拡張はデフォルトでスペースで区切られているので、現在の作業ディレクトリではなく、/home/user3/CIT/testsに作成される「mynewfile、mynewfile1、mynewfile2」ファイルを追加しました。 (もちろん、これを行うよりクリーンな方法があります。)