Reputation: 1
I am new to bash scripting and stackoverflow (first question). I am trying to do a fairly simple thing but I am somehow not getting what I want (tried to use some of the solutions from different threads but with no luck). Perhaps you can help me with a simple solution.
My task: Look through different folders (in some main folder) for for a file named log.txt. If found then move the relevant folder to another location (its a backup folder...the log.txt indicates that this folder needs a backup). In the below layout, I want to mv folder3 along with all its content.
-Main
--folder1
---subfolder
--folder2
---Subfolder2
--folder3
--Subfolder3
--log.txt
#!/bin/bash
MAIN=$(find /home/rwo/Desktop/FROM/* -maxdepth 0 -type d)
for FOLDER in $MAIN; do
if
find $FOLDER -maxdepth 0 -type f -name "log.txt"
then
mv $FOLDER /home/rwo/Desktop/TO
fi
done
In the above case, the recipient folder (TO) ends up receiving Subfolder1, Subfolder2 and Subfolder3 (along with log.txt). What am I doing wrong?
Thanks in advance
Upvotes: 0
Views: 172
Reputation: 7791
With find
and bash
#!/usr/bin/env bash
while IFS= read -r file; do
file=${file%/*}
echo mv -v "${file%/*}" /home/rwo/Desktop/TO
done < <(find main -type f -name 'log.txt')
The echo
is there to show you what's going to happen, remove it if you think the output is ok.
A simple simulation
mkdir -p Main/folder{1..3}
mkdir -p Main/folder1/subfolder
mkdir -p Main/folder2/subfolder2
mkdir -p Main/folder3/subfolder3
touch Main/folder3/subfolder3/log.txt
Create the destination directory
mkdir -p home/rwo/Desktop/TO
check the what is inside the Main directory.
tree Main
Output
Main
├── folder1
│ └── subfolder
├── folder2
│ └── subfolder2
└── folder3
└── subfolder3
└── log.txt
6 directories, 1 file
Now the script to match the Main
#!/usr/bin/env bash
while IFS= read -r file; do
file=${file%/*}
echo mv -v "${file%/*}" home/rwo/Desktop/TO
done < <(find Main -type f -name 'log.txt')
output
mv -v Main/folder3/ home/rwo/Desktop/TO
Removing the echo
will output
renamed 'Main/folder3/' -> 'home/rwo/Desktop/TO/folder3'
The "${file%/*}"
is form of Parameter Expansion Which basically removes the last /
So for example the output of find main -type f -name 'log.txt'
main/folder3/subfolder3/log.txt
Removing the last /
with parameter expansion will leave just the path name
main/folder3/subfolder3/
Apply another parameter expansion to remove the last /
will result to
main/folder3/
Then feeding that to mv
as an argument inside the while read
loop.
The <()
is called Process Substituion
The IFS=
disables the default feature of the builtin read
which removes the trailing and leading white spaces.
Have a look at howto read a file or stream in bash to understand the while read
loop that is posted.
Upvotes: 1