directory path as command line argument in bash - linux

The following bash script finds a .txt file from the given directory path, then changes one word (change mountain to sea) from the .txt file
#!/bin/bash
FILE=`find /home/abc/Documents/2011.11.* -type f -name "abc.txt"`
sed -e 's/mountain/sea/g' $FILE
The output I am getting is ok in this case.
My problem is if I want to give the directory path as command line argument then it is not working. Suppose, I modify my bash script to:
#!/bin/bash
FILE=`find $1 -type f -name "abc.txt"`
sed -e 's/mountain/sea/g' $FILE
and invoke it like:
./test.sh /home/abc/Documents/2011.11.*
Error is:
./test.sh: line 2: /home/abc/Documents/2011.11.10/abc.txt: Permission denied
Can anybody suggest how to access directory path as command line argument?

Your first line should be:
FILE=`find "$#" -type f -name "abc.txt"`
The wildcard will be expanded before calling the script, so you need to use "$#" to get all the directories that it expands to and pass these as the arguments to find.

You don't need to pass .* to your script.
Have your script like this:
#!/bin/bash
# some sanity checks here
path="$1"
find "$path".* -type f -name "abc.txt" -exec sed -i.bak 's/mountain/sea/g' '{}' \;
And run it like:
./test.sh "/home/abc/Documents/2011.11"
PS: See how sed can be invoked directly from find itself using -exec option.

Related

Shell Script to find the file and rename it

My goal is to create a shell script that will search for the file and rename it.
e.g. file abc_123456789.csv should name as abc.csv
to achieve this I have created the script like this.
find /abc/def -type f -name 'abc*' -exec sh -c 'x="{}"; mv "$x" $(echo $x | awk '{sub(/_.*/,"")'; print}')'
Could anyone please help me update the above script to remove the numbers from abc_123456789.csv and make it only abc.csv?

Save output command in a variable and write for loop

I want to write a shell script. I list my jpg files inside nested subdirectories with the following command line:
find . -type f -name "*.jpg"
How can I save the output of this command inside a variable and write a for loop for that? (I want to do some processing steps for each jpg file)
You don't want to store output containing multiple files into a variable/array and then post-process it later. You can just do those actions on the files on-the-run.
Assuming you have bash shell available, you could write a small script as
#!/usr/bin/env bash
# ^^^^ bash shell needed over any POSIX shell because
# of the need to use process-substitution <()
while IFS= read -r -d '' image; do
printf '%s\n' "$image"
# Your other actions can be done here
done < <(find . -type f -name "*.jpg" -print0)
The -print0 option writes filenames with a null byte terminator, which is then subsequently read using the read command. This will ensure the file names containing special characters are handled without choking on them.
Better than storing in a variable, use this :
find . -type f -name "*.jpg" -exec command {} \;
Even, if you want, command can be a full bloated shell script.
A demo is better than an explanation, no ? Copy paste the whole lines in a terminal :
cat<<'EOF' >/tmp/test
#!/bin/bash
echo "I play with $1 and I can replay with $1, even 3 times: $1"
EOF
chmod +x /tmp/test
find . -type f -name "*.jpg" -exec /tmp/test {} \;
Edit: new demo (from new questions from comments)
find . -type f -name "*.jpg" | head -n 10 | xargs -n1 command
(this another solution doesn't take care of filenames with newlines or spaces)
This one take care :
#!/bin/bash
shopt -s globstar
count=0
for file in **/*.jpg; do
if ((++count < 10)); then
echo "process file $file number $count"
else
break
fi
done

Get folder name and rename file name tr Linux bash

I have a script that changes the file name. It takes a directory name and added to the file name. By the way, using tr replaces a string:
0004 the name of the directory (this directory is a script)
- DSC_1234.jpg
result 0004_1234.jpg
The script works if I am in a particular directory. I wanted to change a name yet in subdirectories
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename $CURRENT`
echo $BASENAME
for i in ./*DSC*;do mv -- "$i" "${i//DSC/$BASENAME}";done
The following should work in subdirectories:
for i in $(find . -type f); do dir="$(dirname ${i#./})"; mv "$i" "${i//DSC/$(basename $dir)}"; done
You probably want to use find on your bash script (call that script your_script.sh):
find $ROOT_DIR -type d -exec your_script.sh \;

Bash Script to find files

Good day,
I've found an easy way to find files that have certain content, but I would like to create a bash script to do it quickier,
The script is:
#!/bin/bash
DIRECTORY=$(cd `dirname .` && pwd)
ARGUMENTS="'$#'"
echo find: $ARGUMENTS on $DIRECTORY
find $DIRECTORY -iname '*' | xargs grep $ARGUMENTS -sl
So if I write:
$ script.sh text
It should find in that directory files that contains 'text'
But when I execute this script it always fails, but the echo command shows exactly what I need, what's wrong with this script?
Thank you!
Luis
References: http://www.liamdelahunty.com/tips/linux_find_string_files.php
There are problems with quoting that will break in this script if either the current directory or the search pattern contains a space. The following is more simply, and fixes both issues:
find . -maxdepth 1 -type f -exec grep "$#" {} +
With the proper quoting of $#, you can even pass options to grep, such as -i.
./script -i "some text"
Try this version, with the following changes:
1.Use $1 instead of $# unless you intend to run multiple find/grep to search for multiple patterns.
2.Use find $DIR -type f to find all files instead of find $DIR -iname '*'
3.Avoid piping by using the -exec command line option of find.
4.Do not single quote the command line arguments to your script, this was the main problem with the version you had. Your grep string had escaped single quotes \'search_string\'
#!/bin/bash
DIRECTORY=$(cd `dirname .` && pwd)
ARGUMENTS="$1"
echo find: $ARGUMENTS on $DIRECTORY
find $DIRECTORY . -type f -exec grep -sl "$ARGUMENTS" {} \;
There is no point extracting all the command line arguments and passing it to grep. If you want to search for a string with spaces, pass the string within single quotes from the command line as follows:
/home/user/bin/test-find.sh 'i need to search this'
Why not just run the following?:
grep -R text .

Bash script for searching of files (file types) which are defined in the external file recursively in directory using find command

I'd like to search in the directory structure recursively for files of the specific file types. But I need to pass the file types from the external file. The output should be list where each line is absolute path to the file. I will use the output for further processing.
The external file where is the list of file types looks for example like this (filter.lst):
*.properties
I've tried this (searchfiles.sh):
while read line
do
echo "$(find $1 -type f -name $line)"
done < $2
Echo command inside the script is only for the test purpose. I ran the script:
./searchfiles.sh test_scripting filter.lst
The the output of the echo of the find command was empty. Why? I tried to alter the script in the following way to test if the command is built correctly and the files *.properties exist:
while read line
do
echo "find $1 -type f -name $line"
echo "$(find $1 -type f -name $line)"
done < $2
I've got output:
./searchfiles.sh test_scripting filter.lst
find test_scripting -type f -name *.properties
If I copy manualy "find test_scripting -type f -name *.properties" and paste it to the shell the files are correctly found:
find test_scripting -type f -name *.properties
test_scripting/dir1/audit.properties
test_scripting/audit.properties
test_scripting/dir2/audit.properties
Why does not "find" command process correctly the variables?
The cause of the strange behaviour were hidden characters in the input filter.lst file. The filter.lst was created in the Windows OS and then copied to the Linux OS. Hence the find command didn't find expected files. Test the input file if it contains hidden characters:
od -c filter.lst
0000000 * . p r o p e r t i e s \r \n
0000016
The hidden character is "\r". Edit the script to remove hidden characters using sed command in each line.
while read line
do
echo "$(find $1 -type f -name $(echo $line | sed -e 's/\r$//'))"
done < $2
More about removing hidden characters is in this thread.
Notice: The best way is to run the script in the empty directory. If there is the file with the name e.g. example.properties in the directory where you run the script, the "echo $line" (executed as echo *.properties) will only display the list of .properties files - in this case only file example.properties.

Resources