Change Directory Using Loop in Linux

Bash-change directories in for loop

To handle multiple directories, I would just add another loop:

for dir in ./test/*_out/; do
for file in "$dir"/*.coords; do
./test/sort.pl --in1 "$file" --in2 "$dir/count.txt" \
--out "${file/.coords/.sorted}"
done
done

Or you could use the glob on both levels at the same time, and use dirname or ${file%/*} to get the name of directory the current file is in:

for file in ./test/*_out/*.coords; do
./test/sort.pl --in1 "$file" --in2 "${file%/*}/count.txt" \
--out "${file/.coords/.sorted}"
done

(--in2 "./test/*out/count.txt" won't work, the wildcard isn't expanded in quotes, you get a path with a literal asterisk.)

As for the output file, I'm not exactly sure what it is you want, but if you want all the output files in some other directory, then something like this:

outfile=${file##*/}       # remove directory part of path (or use basename)
# stick new path in, and change extension
outfile=/path/to/output/${outfile/.coords/.sorted}
./test/sort.pl --in1 "$file" --in2 "$dir/count.txt" \
--out "$outfile"

or if you want the "go up one directory", you could use "${file%/*/*}/${file##*/}" to transform /foo/bar/abc.txt to /foo/abc.txt.

Use of CD in Bash For Loop - only getting relative path

I'd suggest using parentheses to run the loop body in a subshell:

for dir in */; do
(
echo $dir
cd $dir
cwd="$PWD"
mkdir -p "VSI"
mv -v *.vsi "$cwd/VSI"
mv -v _*_ "$cwd/VSI"
)
done

Since that's running in a subshell, the cd command won't affect the parent shell executing the script.

How to loop over files in directory and change path and add suffix to filename

A couple of notes first: when you use Data/data1.txt as an argument, should it really be /Data/data1.txt (with a leading slash)? Also, should the outer loop scan only for .txt files, or all files in /Data? Here's an answer, assuming /Data/data1.txt and .txt files only:

#!/bin/bash
for filename in /Data/*.txt; do
for ((i=0; i<=3; i++)); do
./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
done
done

Notes:

  • /Data/*.txt expands to the paths of the text files in /Data (including the /Data/ part)
  • $( ... ) runs a shell command and inserts its output at that point in the command line
  • basename somepath .txt outputs the base part of somepath, with .txt removed from the end (e.g. /Data/file.txt -> file)

If you needed to run MyProgram with Data/file.txt instead of /Data/file.txt, use "${filename#/}" to remove the leading slash. On the other hand, if it's really Data not /Data you want to scan, just use for filename in Data/*.txt.

cd into directory in while loop doesn't work

I see two problems in your code:

  1. You do not test for directories.
  2. Once you cd in the dir, you stay there.

Please try this:

#!/bin/bash

ls -1 | while read d
do
test -d "$d" || continue
echo $d
(cd $d ; echo "In ${PWD}")
done

bash - for loop through multiple directories and their files

Would you please try the following:

#!/bin/bash

for i in my_path/*/; do
year=${i%/}; year=${year##*/} # extract year
year2=$(( year + 19 )) # add 19
for j in "$i"*.nc; do
echo cdo "selyear,${year}/${year2}" "$j" "$j"2
done
done

It outputs command lines as a dry run. If it looks good, drop echo and run.

Bash for loop on directories

I think you have a typo error after "then"...
It makes more sense to be:

then
cd /path/to/data/$D
# command 2

But as advised by cdarke, it is good to avoid to use cd in your script.
You can have the same result like this:

for D in /path/to/data; do
# command 1
if [ -d "$D" ]
then
# command 2
for i in /path/to/data/$D/*.foo
do
# command 3
done
fi
done

Or you could even use find and avoid the if parts (less code makes faster your script):

for D in $(find /path/to/data -maxdepth 1 -type d)
# -type d in find get's only directories
# -maxdepth 1 means current dir. If you remove maxdepth option all subdirs will be found.
# OR you can increase -maxdepth value to control how deep you want to search inside sub directories.


Related Topics



Leave a reply



Submit