Change filenames in a specific folder through bash - linux

I have a folder FOLDER1 with different files in it.
I have several files in the folder with an extension .png
I would like to change the filename of all the files with extension .png with a bash script. I tried to write one but I still didn't arrive to have what I want.
#!/bin/bash
# make sure you always put $f in double quotes to avoid any nasty surprises i.e. "$f"
i=0
for f in *.png
do
echo "${i}Processing $f file..."
i+=1;
echo ${i}
# rm "$f"
done
At the end of the script I would like to have all the files named like:
c-1.png
c-2.png
c-3.png
...
...
...
Could you help me?
Thanks

First note that:
i+=1
is string addition. What you're doing is 0,01,011,0111.... You need:
((++i))
Next you need to split your file name, one way if "." appears only once:
base=$(echo $f | cut -d. -f1)
and finally move:
mv $f ${base}-${i}.png

Sorry, I found my solution .
This code is working perfectly.
#!/bin/bash
# make sure you always put $f in double quotes to avoid any nasty surprises i.e. "$f"
i=0
for f in *.png
do
echo "$i Processing $f file..."
i=$((i+1))
mv $f "c-"$i.png
#echo ${i}
done

#!/bin/bash
i=0
for f in *.png
do
echo "${i}Processing $f file..."
i=$((i + 1))
newname="c-${i}.png"
mv "$f" $newname
done

Related

bash scripts list files in a directory

I'm writing a script that takes an argument which is a directory .
i want to be able to construct list/array with all the files that have a certain extension in that directory and cut their extension .
For example if i have directory containing :
aaa.xx
bbb.yy
ccc.xx
and im searching for *.xx .
my list/array would be : aaa ccc.
I'm trying to use the code in this thread example the accepted answer .
set tests_list=[]
for f in $1/*.bpt
do
echo $f
if [[ ! -f "$f" ]]
then
continue
fi
set tmp=echo $f | cut -d"." -f1
#echo $tmp
tests_list+=$tmp
done
echo ${tests_list[#]}
if i run this script i get that the loop only executes once with $f is tests_list=[]/*.bpt which is weird since $f should be a file name in that directory , and echo empty string.
i validated that i'm in the correct directory and that the argument directory have files with .bpt extensions .
This should work for you:
for file in *.xx ; do echo "${file%.*}" ; done
To expand this to a script that takes an argument as a directory:
#!/bin/bash
dir="$1"
ext='xx'
for file in "$dir"/*."$ext"
do
echo "${file%.*}"
done
edit: switched ls with for - thanks #tripleee for the correction.
filear=($(find path/ -name "*\.xx"))
filears=()
for f in ${filear[#]}; do filears[${#filears[#]}]=${f%\.*}; done

Linux Bash file Reading Lines and words

I apologize if this is a trivial question. I am learning how to use linux bash and this little task is giving me a headache...
So I need to write a script, let's call it count.sh. I want that: for each file in the working directory, prints the filename, the number of lines, and the number of words to the console:
test.txt 100 1023
someOtherfiles 10 233
So far, I know that the following gives me all the files names in the directory. And thanks for all who helped me, I get this working version:
for f in *; do
echo -n "$f"
cat "$f" | wc -wl
done
I would really appreciate your help! Thanks ahead!
P.s. If you know great resources (links for tutorials) for learning about script and you are willing to share it with me. I think I really need to know these basics. Thanks again!
If you must have the file name as the first field in your output, try this:
for f in *; do
if [ -f "$f" ]; then
echo -n "$f"
cat "$f" | wc -wl
fi
done
for f in *; do
if [[ -f $f ]]; then
echo "$f $(wc -wl < "$f")"
fi
done
[[ -f $f ]] processes only files (excludes subdirectories) and also handles the case where the directory is empty (in which case * is (by default) left unexpanded, i.e. assigned to $f as is).
echo "$f $(wc -wl < "$f")" uses command substitution ($( ... )) to directly include the output from the enclosed command in the output string passed to echo.
Note that the reason that < is used to direct the content of file $f to wc via stdin is that wc would otherwise append the name of the input file to its output (thanks, #R Sahu).

Editing every file in a directory after opening it bash

Looking around I didn't see exactly what I was looking for. Some similar stuff, but for some reason what I tried so far hasn't worked.
My main goals:
run script in my current directory
open the picture to see what it is
rename the picture i just viewed
repeat the process without running the script again
These were the sources I attempted to follow:
Bash Shell Loop Over Set of Files
Bash loop through directory and rename every file
How to do something to every file in a directory using bash?
==================================================================================
echo "Rename pictures. Path"
read path
for f in $path
do
eog $path
echo "new name"
read newname
mv $path $newname
cat $f
done
You should pass the script an argument rather than trying to make it interactive. You also have numerous quoting problems. Try something like this instead (untested):
#!/usr/bin/env bash
moveFile() {
local newName=
until [[ $newName ]]; do
printf '%s ' 'new name:'
read -er newName # -e implies Bash with readline
echo
done
mv -i "$1" "${1%/*}/${newName}"
}
if [[ ! -d $1 ]]; then
echo 'Must specify a path' >&2
exit 1
fi
for f in "$1"/*; do
eog "$f"
moveFile "$f"
done
You might want to try something like this:
for f in $*; do
eog $f
echo "new name:"
read newname
mv $f $newname
done
If you name the script, say, rename.sh, you can call
./rename.sh *gif
to review all files with extention 'gif'.
Using find command allows you to search for image files in the specified directory recursively.
echo -n "Rename pictures. Input image directory: "
read path
for f in `find $path -type f`
do
eog $f
echo -n "Enter new name: "
read newname
mv $f $newname
echo "Renamed $f to $newname."
done

Renaming xml file extension using bash script

I have a directory which has many folder and each folder contains a list of XML files. I am writing a bash script that traverses through the files and renames the extension of the file to "manual" if the size of the file is greater than 65Mb. This is my first writing a shell script and I was able to write the code for traversing the files but I am having difficulty in the renaming part.
for file in $dir
do
size=$(stat -c%s "$file")
if test "$size" -gt "68157440"; then
echo "Before Renaming...."
echo $file
echo "After renaming"
mv *.manual `basename $file`.xml
echo $file
else
echo $file >> outlog.log
fi
done
an example of $file is,
/apps/jAS/dev/products-app/BConverter/data/supplier-data/TF/output/Fiber Optics and Fiber Management Solutions/Fiber Optic Cable Assemblies.xml
mv *.manual `basename $file`.xml
If you want to change the extension of $file from xml to manual, do instead
mv "$file" "${file%.xml}".manual
What exactly is the difficulty you're having?
If it's white space in file names, try
mv *.manual `basename "$file"`.xml
Note that your script will not work if *.manual expands to more than one file name.
No need for a script on this, combination of find and xargs should do the trick:
find . -size +65M | xargs -IQ mv Q Q.manual
The little-used -I option to Xargs:
runs each input as a separate command, and
lets you replace the filename, so you can use it multiple time, ideal for a mv

Renaming a set of files to 001, 002,

I originally had a set of images of the form image_001.jpg, image_002.jpg, ...
I went through them and removed several. Now I'd like to rename the leftover files back to image_001.jpg, image_002.jpg, ...
Is there a Linux command that will do this neatly? I'm familiar with rename but can't see anything to order file names like this. I'm thinking that since ls *.jpg lists the files in order (with gaps), the solution would be to pass the output of that into a bash loop or something?
If I understand right, you have e.g. image_001.jpg, image_003.jpg, image_005.jpg, and you want to rename to image_001.jpg, image_002.jpg, image_003.jpg.
EDIT: This is modified to put the temp file in the current directory. As Stephan202 noted, this can make a significant difference if temp is on a different filesystem. To avoid hitting the temp file in the loop, it now goes through image*
i=1; temp=$(mktemp -p .); for file in image*
do
mv "$file" $temp;
mv $temp $(printf "image_%0.3d.jpg" $i)
i=$((i + 1))
done
A simple loop (test with echo, execute with mv):
I=1
for F in *; do
echo "$F" `printf image_%03d.jpg $I`
#mv "$F" `printf image_%03d.jpg $I` 2>/dev/null || true
I=$((I + 1))
done
(I added 2>/dev/null || true to suppress warnings about identical source and target files. If this is not to your liking, go with Matthew Flaschen's answer.)
Some good answers here already; but some rely on hiding errors which is not a good idea (that assumes mv will only error because of a condition that is expected - what about all the other reaons mv might error?).
Moreover, it can be done a little shorter and should be better quoted:
for file in *; do
printf -vsequenceImage 'image_%03d.jpg' "$((++i))"
[[ -e $sequenceImage ]] || \
mv "$file" "$sequenceImage"
done
Also note that you shouldn't capitalize your variables in bash scripts.
Try the following script:
numerate.sh
This code snipped should do the job:
./numerate.sh -d <your image folder> -b <start number> -L 3 -p image_ -s .jpg -o numerically -r
This does the reverse of what you are asking (taking files of the form *.jpg.001 and converting them to *.001.jpg), but can easily be modified for your purpose:
for file in *
do
if [[ "$file" =~ "(.*)\.([[:alpha:]]+)\.([[:digit:]]{3,})$" ]]
then
mv "${BASH_REMATCH[0]}" "${BASH_REMATCH[1]}.${BASH_REMATCH[3]}.${BASH_REMATCH[2]}"
fi
done
I was going to suggest something like the above using a for loop, an iterator, cut -f1 -d "_", then mv i i.iterator. It looks like it's already covered other ways, though.

Resources