Reputation: 21
I need a way in which I can within a for loop generate a lot a directory using mkdir
.
for i in $(seq 1 1 ${k})
do
mkdir ...
done
The name of folder is a name with k
numbers, such as 0_0_1
in which case k = 3.
The for-loop has to generate different names in which the position of 1
changes. so the names generated and directory created should be
1_0_0
, 0_1_0
, 0_0_1
for k = 3
and in that order as well.
is this possible?
Upvotes: 2
Views: 971
Reputation: 103744
To create your first pattern for any value of n
you can create a binary number with bc
and then insert the _
between each digit with awk
:
$ n=5
$ fn=$(echo "obase=2;2^($n-1)" | bc | awk '$1=$1' FS= OFS="_" )
$ echo "$fn"
1_0_0_0_0
Then you can rotate that pattern with awk
in a Bash loop. Here with a larger n
to demonstrate:
n=7
fn=$(echo "obase=2;2^($n-1)" | bc | awk '$1=$1' FS= OFS="_" )
for (( i=1 ; i<=$n ; i++ )); do
(( i > 1 )) && fn=$(echo "$fn" | awk '{t=$(n-1); $(n-1)=$n; $n=t; print }' n="$i" FS="_" OFS="_")
echo "$fn" # here mkdir "$fn"
done
1_0_0_0_0_0_0
0_1_0_0_0_0_0
0_0_1_0_0_0_0
0_0_0_1_0_0_0
0_0_0_0_1_0_0
0_0_0_0_0_1_0
0_0_0_0_0_0_1
Upvotes: 0
Reputation: 437111
A pure Bash solution (no calls to external utilities): Tip of the hat to archimiro for encouraging me to initialize the array in a Bash loop too.
# Determine the number of digits
k=3
# Create an array with the specified number of digits
# initialized to 0s (e.g., with k = 3, `( 0 0 0 )`).
arr=()
for (( i = 0; i < k; ++i )); do arr[i]='0'; done
# Loop over all digits and set each one to 1 in isolation.
IFS='_' # set IFS, the internal field separator, also used when printing arrays as strings
for (( i = 0; i < k; ++i )); do
arr[i]=1
# Inside "...", with index [*], the array elements are joined with
# the 1st char. in $IFS.
echo "${arr[*]}"
arr[i]=0
done
Note: For brevity I've omitted saving and restoring the original $IFS
value above, something that is advisable in real-world scripts.
The above yields:
1_0_0
0_1_0
0_0_1
Upvotes: 2
Reputation: 2356
This might be the ugliest way to do it, or at least not the fastest one. But anyhow here it goes:
k=3
template=$(printf "%0*d" "$k" | sed 's/./&_/g')
for ((i=1; i<=k*2; i+=2)); do
echo $(sed "s/./1/$i" <<<${template%_})
done
And of course we can try to remove the sed
inside the loop to speed things a bit:
k=3
template=$(printf "%0*d" "$k" | sed 's/./&_/g')
for ((i=0; i<k*2; i+=2)); do
j=i+1
file=${template:0:$i}1${template:$j}
echo ${file%_}
done
Upvotes: 0
Reputation: 21
Here is a double for-loop that will print the appropriate names to stdout
k=4
for i in $(seq 1 1 ${k})
do
name="0"
if [[ "$i" -eq "1" ]]; then
name="1"
fi
for j in $(seq 2 1 ${k})
do
if [[ "$i" -eq "$j" ]]; then
name="${name}_1"
else
name="${name}_0"
fi
done
echo "$name" #to make directories replace with mkdir "$name"
done
Running this script with k set to 4 gives the output
$ ./filemaker.sh
1_0_0_0
0_1_0_0
0_0_1_0
0_0_0_1
Upvotes: 1
Reputation: 241768
You can use a loop to create the first file name, then use substitution in a loop to create the other names:
#!/bin/bash
k=4
s=''
for ((i=1; i<k; i++)) ; do
s+=0_
done
s+=1
while [[ $s != 1* ]] ; do
echo "$s"
s=${s/0_1/1_0}
done
echo "$s"
Upvotes: 1