Writing a bash script to find all files in a directory that start with a, and do nothing if one exist [duplicate] - linux

This question already has answers here:
Do not show results if directory is empty using Bash
(3 answers)
Closed 4 years ago.
So I have to find all the files in the directory that start with the letter a, and list them out. This is pretty easy by doing
cd some_directory
for file in a*; do
echo "$file"
done
However I want that if there are no files present that match a*, then the for loop will not run at all. Currently, if this is the case then the shell will echo
a*
Is there a way to do this? Thank you

Your text is opposite of your title, in my answer below I've assumed the text is your intention and your title is incorrect:
globs can be made to act like this with the bash shell option "nullglob":
shopt -s nullglob

An alternative is to use find and ignore errors by piping stderr to /dev/null
for file in $(find a* 2>/dev/null); do
echo "$file"
done

Related

Shell rename a lot of files recursively [duplicate]

This question already has answers here:
Find multiple files and rename them in Linux
(13 answers)
Closed 3 years ago.
I want to rename a lot of files in sub directories with a shell script/command, and I've tried different way without any success.
Here is the files I've got:
root/FOLDER1/media-125150-payasage151.jpg
root/FOLDER1/media-125165-payasage125.jpg
root/FOLDER2/media-1266165-payasage110.jpg
root/FOLDER2/media-1266165-portrait151.jpg
and I want to replace every "payasage" by "paysage"
root/FOLDER1/media-125150-paysage151.jpg
root/FOLDER1/media-125165-paysage125.jpg
root/FOLDER2/media-1266165-paysage110.jpg
root/FOLDER2/media-1266165-portrait151.jpg
I've tried RegExr with rename command or even with a mv approch...
thanks!
Try something along the lines of
for OLD in root/*/media-*-payasage*.jpg; do
NEW=$(echo "$OLD" | sed 's/payasage/paysage/g')
test "$OLD" != "$NEW" && mv "$OLD" "$NEW"
done

star wildcard in bash [duplicate]

This question already has answers here:
Rename multiple files in shell [duplicate]
(4 answers)
Closed 4 years ago.
I've got a small problem with my bash script. I try to change file name in current directory for whole files with txt extension to text extension. For exampel 1.txt to 1.text
My script looks like this now:
#!/bin/bash
FILES=`ls /home/name/*.txt`
NAME=*.txt
RENAME=*.text
for file in FILES
do
mv $NAME $RENAME
done
i try whole combination with single, double quotes and backticks and I receive errors all the time.
Do you have some ideas how to receive wildcards "*" in bash?
Thanks.
That's not at all how you do that.
#!/bin/bash
shopt -s nullglob
OLD=.txt
NEW=.text
FILES=(/home/name/*"$OLD")
for file in "${FILES[#]}"
do
mv "$file" "${file%$OLD}$NEW}"
done
There are a number of issues with your script. Firstly, you shouldn't run ls and attempt to store its output like that. If you want to iterate through those file, just do it in the loop:
for file in /home/name/*.txt
Now the shell is doing all the work for you, and as a bonus handling any kind of weird filenames that you might have.
In your example you were looping over the literal string "FILES", not the variable, but I guess that was just a typo.
The built-in way to change the filename is to use a parameter expansion to remove the old one, then concatenate with the new one:
old=txt
new=text
for file in /home/name/*"$old"
do
mv "$file" "${file%$old}$new"
done
If it is possible that there are no files matching the glob, then by default, the /home/name/*.txt will not be expanded and your loop will just run once. then you have a couple of options:
use shopt -s nullglob so that /home/name/*.txt expands to null, and the loop is skipped
add an explicit check inside the loop to ensure that $file exists before trying to mv:
for file in /home/name/*"$old"
do
[ -e "$file" ] || continue
mv "$file" "${file%$old}$new"
done
You can use rename to rename filenames.
rename .txt .text /home/name/*.txt
And if you want to do this by looping, you can
for FILE in /data/tmp/*.txt; do
mv "${FILE}" "${FILE/.txt/.text}"
done

Create symlink of every file in a folder tree [duplicate]

This question already has answers here:
symlink-copying a directory hierarchy
(7 answers)
Closed 4 years ago.
I need a Bash script that will create a symlink for every *.mp3 file in folder X (and its subfolders), and store those symlinks in folder Y, without subfolders and probably skipping duplicates.
For the curious, this is to automate a radio station using Libretime.
And sorry if this is a dumb question, I never used a Bash script.
As in the comment: use find to create a list of the mp3-files:
find /top/dir/for/mp3s -name '*mp3'
You will want to use that output to loop over it, so:
find /top/dir/for/mp3s -name '*mp3' | while read mp3file, do
# do the linking
done
You want create a link in a specific directory, probably with the same filename. You can get the filename with basename. So, that would make it something like this:
find /top/dir/for/mp3s -name '*mp3' | while read mp3file; do
filename=$(basename $mp3file)
ln -s $mp3file /dir/where/the/links/are/$filename
echo Linked $mp3file to /dir/where/the/links/are/$filename
done
However, this will probably give you two types of error:
If the mp3 filename contains spaces, basename will not produce the correct filename and ln will complain. Solution: use correct quoting.
If you have duplicate filenames, ln will complain that the link already exists. Solution: test if the link exists.
Because you're not destroying anything, you can try it and actually see the problems. So, our next iteration would be:
find /top/dir/for/mp3s -name '*mp3' | while read mp3file; do
filename=$(basename "$mp3file")
if [ ! -l "/dir/where/the/links/are/$filename" ] ; then
ln -s "$mp3file" "/dir/where/the/links/are/$filename"
echo "Linked $mp3file to /dir/where/the/links/are/$filename"
else
echo "Not linked $mp3file; link exists"
fi
done
That should give you a fairly good result. It also gives you a good starting point.

Change file names iteratively in Linux [duplicate]

This question already has answers here:
Rename multiple files in bash
(3 answers)
Closed 8 years ago.
The only way I am aware of to do this operation is with a for loop iterating over each file:
for file in *something.txt; do
out=\`echo $file | sed 's/something/else/'\`; mv $file $out;
done
I was wondering if there is any other way or shortcut for it (using GNU bash).
There is also simple substring replacement provided as part of bash itself:
mv $file ${file/something/else}
example:
$ touch {1..3}something.txt
$ ( for i in *something.txt; do mv $i ${i/something/else}; done )
$ ls -1 *else*
1else.txt
2else.txt
3else.txt
There's rename and the same basic loop concept as in your post only in whatever programming language you choose.

List paths with find when the filename contains spaces [duplicate]

This question already has answers here:
Iterate over a list of files with spaces
(12 answers)
Closed 9 years ago.
I have this code
for i in $(find pwd)
do
echo $i
done
the problem is if the file name contains spaces, it prints on a separate line
how can I list all of the files in some directory including files that contains spaces
This would have the intended effect of your example:
find /path/to/somewhere
That is, no need to wrap a for loop around it.
But I'm guessing you want something more than just echoing. Perhaps call a script for each file? You can do that with:
find /path/to/somewhere -exec path/to/script.sh {} \;
where {} will be replaced for each filename found.
I would use while read for this.
find . | while read i; do echo $i; done;
Edit:
Alternatively, you could just do ls -a1
here is the solution
IFS=$'\n'
for i in $(pwd)
do
echo $i
done

Resources