Hello I am trying to write a simple bash script,
the problem I am having is that I want to iterate through the 4th,5th,6th and the 7th files returned from the ls command and then to check if these files have write or read permissions and if they do so, to do a simple copy of these files to another directory. What I’ve done so far is to check if they have the permissions needed and then if they do, to copy them to the /tmp
directory.
My solution:
#!/bin/sh
for f in *
do
if [ -w "$f" ] || [ -r "$f" ]; then
cp $f /tmp
fi
done
The way to get the 4th to 7th file names is through ls | head -7 | tail -4
, but how can I iterate specifically though these files names only? Basically how can I make it so the *
list in the for loop can be these 4 file names?
Thank you very much.
Advertisement
Answer
Do not try to parse the output of ls
. See Why you shouldn’t parse the output of ls
Using globbing, store filenames into an array and iterate through indices from 3 to 6 (both inclusive). Notice that array indices begin from zero in bash
. For example, using a C style for
loop
#!/bin/bash files=(*) for ((i = 3; i <= 6; ++i)); do if [[ -r ${files[i]} || -w ${files[i]} ]]; then cp "${files[i]}" /tmp fi done
or using a traditional for
loop with array slices:
files=(*) for file in "${files[@]:3:4}"; do if [[ -r $file || -w $file ]]; then cp "$file" /tmp fi done
Alternatively, as mentioned in the comments, a counter can be implemented to skip the first 3 files and break the loop after the 7th iteration, without resorting to an array:
itr=0 # iteration count for file in *; do ((++itr < 4)) && continue ((itr > 7)) && break [[ -r $file || -w $file ]] && cp "$file" /tmp done