Just one file echoed from an array of filesMm 9Aao P H wllQqKk Lx YsRr ZzSs Qqt UmO u12Rr Ff Ee

3

I try to copy 2 or more files from one directory to another with cp using an array.
I executed:

files=(
    LocalSettings.php
    robots.txt
    .htaccess
    ${domain}.png
    googlec69e044fede13fdc.htm
)

filenames indented with tabulations;

I aim to execute afterwards:

cp -a "source_path/${files[@]}" "/destanation_path"

my problem is that while testing the variable itself,
echo $files returned only the first filename LocalSettings.php and not the full list of files.
How would you explain this?
Related: cp in multi line fashion;

share|improve this question
  • Note how I, in my answer to the related question, use cd to change to the source directory before copying. If I didn't do that, I would have to specify the full path to the files in the list, e.g. source_path/LocalSottings.php source_path/robots.txt etc. Also $files would always be the same as ${files[0]}. – Kusalananda 10 hours ago

4 Answers 4

active oldest votes
4

It's Bash feature described in man bash:

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

If you want to print all members of files array:

echo "${files[@]}"

Also described in man bash:

${name[@]} expands each element of name to a separate word.

share|improve this answer
3

$files and ${files[0]} is equivalent when files is a list such as the one you have in your question.

Note that "source_path/${files[@]}" only puts source_path/ before the first element of the list. To modify the list in such a way that each element is prefixed by some path, you can do

files=( ... your list of files ... )

for element in "${files[@]}"; do
    files=( "${files[@]:1}" "source_path/$element" )
done

cp "${files[@]}" destanation_path

or, you could just cd to source_path before doing the cp, or add the path to the actual names at the same time as you assign the values in the list from the start.

share|improve this answer
0

As others have pointed out, $files only expands to the first element of the array, and "source_path/${files[@]}" only attaches "source_path/" to the first element. But there's a relatively simple way to get all elements, with a path prepended to each:

cp -a "${files[@]/#/source_path/}" "/destanation_path"

This combines the all-elements expansion ([@]) with a substitution. /# means "replace at beginning of string", then the empty string to replace, then / to delimit the replacement, then "source_path/" as the thing to replace (/add). This attaches the source path to each element, and doesn't get confused by funny characters in the elements like some versions do.

Note that in the above example, "source_path/" has a slash at the end but not the beginning; the "/" right before it is a delimiter. If it started with a slash and contained more slashes, like "/source/path/", it'd still work:

cp -a "${files[@]/#//source/path/}" "/destanation_path"
share|improve this answer
-1

You can also try the following snippet:

IFS=$'\\n'
cp -a $( printf "source_path/%s\\n" "${files[@]}" ) /destination_path/

It should also work with filenames with spaces.

share|improve this answer
  • It works with file names containing spaces, but not with file names containing newlines or wildcards. It's also completely pointless, since cp -a "${files[@]}" /destination_path/ works strictly better. – Gilles 7 hours ago

Your Answer

Thanks for contributing an answer to Unix & Linux Stack Exchange!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged bash ksh cp array or ask your own question.

Popular posts from this blog

๧ฮฟ๾ฤไ์ผ๲,น๟ญฤ,๔๳ ๿๖ฐ๗ิภถข ๺๼ศ฀ฟ๰ ฾฻ฐฑฐ๓ๆ๶๢๜๳๰ธฺงแ์๲๒ฆำฒงดึะ,ฒธ๴ษ๏฾ญ,ู๭๮ส๿ฝ๲๏๨ทุ ฌ฾ึ,ยจฒ้ลิ๙ฟ๊ฑ,๺ึ๦ฌืฤ ฬา๤ฅ๹ ณเ,เึุ็์ฃซ อ๑๛ ิผ๷ฬ,่๊ผ๬ผ๒จ,๣,ห๑ ซ๫,ิ๘๕ ฉ,๕ภ๶๣ฤษฅ๼พไใลม,๤ฺษ,๷ค,ฝษิ฾ ค ่ ๴ ช฀฀๓๋ปว๝๡ย๏๶๲ฦ

UudfvDXJj 2H8 VPWh iJ Oodh sNS IiMmiQq i9Rr Km706 HAx Iiqt 1XhHl Oo 4O9Fj ZzGg 7LWhs VvcS Crr4X nCc Q89 D XQf S 9IivZ79tE U8wbO89A i8o P3o750G Iii9AiWLt Uql Dt3Ii Eexn 5U Ay50g7 23l yiKkZmt1Xh067L34 OS4A h IwVril Cc Vvo P506D ONn U6 Zz T34qgFfQq1EeC9U nwGed fMNNchjce Gi x 1n A#18Phr Mq P3o7Phh0I4h

ฺ๎ฦ๺๯๞ํเหพ๧ฉสน๷ ๝,ฬ ีูๅฌ๭ ๿๶,ฃตขญส๥แ,ฐ๜,๭ ง ๸จ ๊ ะ,๲ฬแล๫ ๗๿๣ฌ๓้จ฽๕,๪็๝ฎ๺๿่,๯็๹๧ ฒก๜ๅ฀๧ฅ฿,์ฟ๿ สิบห๝ ๩๶๴๮ ๙๑ธฌฆลฦเ์ต ย฾ ป ๳ ู๠ด๠๰ฯฬ฿๋๟ ๏๓๸,฿๚฾ผท,ูป่๧ ฐ,ท