This question already has answers here:
Bash array with spaces in elements
(14 answers)
How can I handle an array where elements contain spaces in Bash?
(3 answers)
Closed 2 years ago.
In a script such as this
#! /bin/bash -i
arguments=(arg1 "arg2 has many spaces")
echo arguments count = ${#arguments[#]}
echo arguments = ${arguments[#]}
echo ls ${arguments[#]}
ls ${arguments[#]}
How can I keep arg2 as a single argument to ls?
This is the actual output:
arguments count = 2
arguments = arg1 arg2 has many spaces
ls arg1 arg2 has many spaces
ls: arg1: No such file or directory
ls: arg2: No such file or directory
ls: has: No such file or directory
ls: many: No such file or directory
ls: spaces: No such file or directory
This shows that arguments initially has 2 elements but when it is used as arguments in the ls command the quotes are no longer there (obviously, since they were remove already when arguments was initialized) so ls sees 5 arguments.
How can I apply quoting to each of the array elements separately in order to give ls two arguments by keeping the second element together?
(In the real case I don't know the actual content of the array and ls is only an example which illustrates the problem.)
Related
This question already has answers here:
Creating an array from a text file in Bash
(7 answers)
Closed 1 year ago.
This is how the script gets started over the terminal:
echo 'username1 username2 username3' | ./security_check.sh
This is the part of the program which should read the stdin and put it into an array:
while read -r line_input
do
i_users[i]=$line_input
i+=1
done
IFS is not set to something different in this script.
After the input is saved in an array it should be able to get printed like this:
for i in ${i_users[#]}
do
echo "$i"
done
This script takes the whole input through stdin and puts it just in i_users[0].
How can I fix this? The array i_users was declared with declare -a i_users at the beginning of the script
Consider:
while read -r line_input is going to read data one line at a time
the script has one line of input (username1 username2 username3)
so the array ends up with a single entry (index=0 / value=username1 username2 username3)
To break the single line of input into separate array entries you have a few options, one being the read -a suggested by #choroba:
$ cat security_check.sh
#!/bin/bash
read -ra i_users
typeset -p i_users
Running OP's example script call:
$ echo 'username1 username2 username3' | ./security_check.sh
declare -a i_users=([0]="username1" [1]="username2" [2]="username3")
NOTE: This works for a single line of input (as shown in OP's sample script call).
This question already has answers here:
How can I store the "find" command results as an array in Bash
(8 answers)
Closed 3 years ago.
When using the following command within a bash array, it loses the line separation of the array elements.
array=$(find "${PWD%/*}" -name '*.dmg')
If I redirect the path of the find command, without storing it in a variable, but storing it to a text file, it gives the desired result.
find "${PWD%/*}" -name '*.dmg' > Out.txt
But I would like to use the result as a variable in Bash and to loop through it.
In this case the find command should return an array with the path of all .dmg files in a directory. I want to loop through this array with the hdiutil mount command in order to mount all the .dmg files in the directory.
You can use mapfile to safely transfer your found files into an array.
#!/usr/bin/env bash
declare -a array
mapfile -d '' array < <(find "${PWD%/*}" -name '*.dmg' -print0 2>/dev/null)
find -print0 option produces null delimited strings so spaces, tabs and carriage return in file names are preserved safely.
mapfile -d '' array reads stdin with a null delimiter to populate array
< <(commands group) injects the commands group's output into the stdin of the other commands group.
The result is, that the output of find is mapped into array.
For older Bash 3.2 from MacOS lacking mapfile, here is an alternate way to populate array:
#!/usr/bin/env/bash
declare -a array
while read -r -d ''; do
array+=("$REPLY")
done < <(find "${PWD%/*}" -name '*.dmg' -print0 2>/dev/null)
This question already has answers here:
How to pass an array argument to the Bash script
(8 answers)
passing multiple arrays as a parameter in bash
(2 answers)
Closed 3 years ago.
I have a bash script that I need to run for a series of files. The script takes 4 arguments. The first ref is a file, fun is a directory, R1arr and R2arr each are arrays containing a series of files with specific features in a given directory.
My script.sh is as follows:
ref="$1"
fun=$2
R1arr="$#"
R2arr="$#"
analyseReads -i "$ref" -o "$fun" --left "${R1arr[#]}" --right "${R2arr[#]}"
And I run it for various files as follows:
FORWARD=($(for i in Sample_STE*/*R1; do echo $i; done))
REVERSE=($(for i in Sample_STE*/*R2; do echo $i; done))
bash script.sh "$ref" "$fun" "${FORWARD[#]}" "${REVERSE[#]}"
I get an error since "${FORWARD[#]}" and "${REVERSE[#]}" does not only contain the files in the array FORWARD and REVERSE but it also contains "$ref" and "$fun". Why does this happen and how could I solve this issue?
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 5 years ago.
I am writing a Bash Shell script, which reads a bunch of lines from a file, and tries to append each line to an array, thus:
# counter variable
i=0
cat doc.txt | while read -r line; do
myArr[i]="$line"
((i=i+1))
done
The file doc.txt contains one word in every line. When I print the array (through echo ${myArr[#]} or for x in ${myArr[#]};do echo $x; done), my array seems to be empty. What am I doing wrong? Thanks!
Edit: I also tried doing this in Ksh, with the same results. An answer in either Bash or Ksh is acceptable, since I seem to be having the same issue in both.
You are running the while loop in a subshell, so any changes you make to the array disappear once that shell exits. Use input redirection instead:
while IFS= read -r line; do
myArr+=("$line")
done < doc.txt
If you using bash 4.0 or later, you can use a single command
readArray -t myArr < doc.txt
This question already has answers here:
Capturing output of find . -print0 into a bash array
(13 answers)
Closed 7 years ago.
I would like to take the output of something that returns lines of elements possibly containing spaces to a bash array, with each line getting its own array element.
So for example:
find . -name \*.jpg
... may return a list of filenames. I want each filename to be assigned to an array. The simple solution doesn't work in general, because if there are spaces in filenames, the words get their own array element.
For example, start with this list of files in a directory:
FILE1.jpg
FILE2.jpg
FILE WITH SPACES.jpg
Try:
FILES=( $(find . -name \*.jpg) )
And you get (<> added for emphasis of individual elements):
$ for f in "${FILES[#]}"; do echo "<$f>"; done
<./FILE>
<WITH>
<SPACES.jpg>
<./FILE1.jpg>
<./FILE2.jpg>
This is not likely what you want.
How do you assign lines to array elements regardless of the lines containing spaces?
Set IFS before making the assignment. This allows bash to ignore the spaces by using only "\n" as the delimiter:
IFS=$'\n'
FILES=( $(find . -name \*.jpg) )
Now you get the result:
for f in "${FILES[#]}"; do echo "<$f>"; done
<./FILE WITH SPACES.jpg>
<./FILE1.jpg>
<./FILE2.jpg>
Note that how you access the array is important as well. This is covered in a similar question: BASH array with spaces in elements