[英]Why the Linux command CP behave differently in CLI and in script?
我想復制一堆Verilog / systemverilog源代碼,所以我使用CP和通配符表達式:
cp <some_dir>/*.{v,sv,svh} .
有用。 但是當我將它放到具有完全相同行的腳本時,CP命令會失敗並顯示日志:
cp: cannot stat `../../mytest/spiTest/*.{v,sv,svh}': No such file or directory
這是怎么回事?
PS:我使用bash作為shell。
這是我的腳本:
#!/bin/bash
rdir=../../mytest/spiTest
f1="$rdir/bench.lst"
f2="$rdir/cphex" #the script to copy rom data
f3="$rdir/make*" #makefile scripts
f4="$rdir/*.hex" #rom files
f5="$rdir/*.{v,sv,svh}" #testbench files
echo 'Copying files...'
cp $f1 $f2 $f3 $f4 .
cp $f5 .
我把第一行更改為
#!/bin/bash -vx
並再次運行此腳本,我得到:
#!/bin/bash -vx
rdir=../../mytest/spiTest
+ rdir=../../mytest/spiTest
f1="$rdir/bench.lst"
+ f1=../../mytest/spiTest/bench.lst
f2="$rdir/cphex" #the script to copy rom data
+ f2=../../mytest/spiTest/cphex
f3="$rdir/make*" #makefile scripts
+ f3='../../mytest/spiTest/make*'
f4="$rdir/*.hex" #rom files
+ f4='../../mytest/spiTest/*.hex'
f5="$rdir/*.{v,sv,svh}" #testbench files
+ f5='../../mytest/spiTest/*.{v,sv,svh}'
echo 'Copying files...'
+ echo 'Copying files...'
Copying files...
cp $f1 $f2 $f3 $f4 .
+ cp ../../mytest/spiTest/bench.lst ../../mytest/spiTest/cphex ../../mytest/spiTest/makefile ../../mytest/spiTest/makefile.defines ../../mytest/spiTest/rom.hex ../../mytest/spiTest/rom_if.hex .
cp $f5 .
+ cp '../../mytest/spiTest/*.{v,sv,svh}' .
cp: cannot stat `../../mytest/spiTest/*.{v,sv,svh}': No such file or directory
檢查腳本的第一行。 它可能是:
#!/bin/sh
它將shell從BASH切換到Bourne Shell。 采用
#!/bin/bash
代替。
[編輯]你遇到了擴展問題。 BASH有一定的順序,可以擴展模式和變量。 這意味着:
f5="$rdir/*.{v,sv,svh}" #testbench files
引用,因此此時不會發生文件名擴展。 僅展開變量$rdir
。 什么時候
cp $f5 .
執行后,BASH首先查找要擴展的文件名,但沒有。 然后它擴展變量( f5
)然后用兩個參數調用cp
: ../../mytest/spiTest/*.{v,sv,svh}
.
../../mytest/spiTest/*.{v,sv,svh}
和.
。 由於cp
期望shell已經執行了文件名擴展,因此會出現錯誤。
要解決此問題,您必須使用數組:
f5=($rdir/*.{v,sv,svh})
這將替換變量,然后展開文件名並將所有內容放入數組f5
。 然后,您可以使用此數組調用cp
,同時保留空格:
cp "${f5[@]}" .
這里的每一個角色都很重要。 [@]
告訴BASH在這里擴展整個數組。 引述說:保留空白。 {}
必須告訴BASH [@]
是要擴展的變量“name”的一部分。
這是問題:替換的順序。 Bash 在變量擴展之前執行大括號擴展。 在行cp $f5 .
,bash會這樣做:
cp ../../mytest/spiTest/*.{v,sv,svh} .
.{v,sv,svh}
。 它找不到, nullglob
未設置,因此模式不會從命令中刪除 現在命令已執行並因您看到的錯誤而失敗。
https://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
解決方案:
eval cp $f5 .
這條線
f5="$rdir/*.{v,sv,svh}" #testbench files
可能是錯的。 首先,避免在行尾注釋,它們應該(至少為了可讀性)在一個單獨的行中。 然后,避免在變量賦值中使用globbing。 所以刪除該行,然后再編碼(也就是說,將舊的cp $f5 .
替換為cp $f5 .
)
cp "$rdir"/*.{v,sv,svh} .
順便說一句,我會測試"$rdir"
確實是一個目錄
if [ ! -d "$rdir" ] ; then
echo invalid directory $rdir > /dev/stderr
exit 1
fi
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.