Is my bash script accurate enough to check if the list of images are being referred anywhere in directory? - bash

I have a list of images which I wanted to delete if they are not being referred anywhere. My directory consists of multiple directories and within them, there are .js files. I need to search each image name in the above files. If they are referred anywhere, I need to output them so I will retain those images.
My script goes like this: I am trying to check each image in the following .js or .json files in the entire directory ( includes multiple directories inside) and output them to c.out if any of these files contain the above image name. Am I doing it right? I still could see some images are not coming in output even if they are being used.
#!/bin/bash
filename='images.txt'
echo Start
while read p; do
echo $p
find -name "*.js" | xargs grep -i $p > c.out
done < $filename
images.txt contains:
a.png
b.png
c.jpeg
....

Step 1: Keep a text file with list of images ( one name per line ), use dos2unix file_name if the file is generated/ created on Windows machine
Step 2: Run find /path/to/proj/dir -name '*.js' -o -name '*.json' | xargs grep -Ff pic_list.txt
You get the list of paths where those images are being referred.
Thanks #shelter for the answer

Related

Zip together files that have filenames that match recursively through directories

Consider a file system like so:
folderA
- one.png
- two.png
- three.png
folderB
- one.png
- two.png
- three.png
folderC
- one.png
- two.png
- three.png
I want to zip together all of the .png's that match one.png into a .zip file named one.zip. Important to note that it should only search filenames specifically and not look inside of files, because code that is generating these .png's exists and I don't want to be matching anything that isn't an actual .png.
I tried search around but with the keywords I know to use, I get a lot of results about searching within a .zip file.
I'm on OSX Mojave. Would appreciate any help!
Thanks,
Adhi
Well, you can go crazy and put all the one.png files into one.zip, all the two.png files into two.zip, etc:
for file in $( find -name \*.png | sed 's:.*/::' | sort -u ); do
zip $(basename $file .png).zip $( find -name $file )
done
base='one'
mapfile -t files < <(find . -name "${base}.png")
zip "${base}.zip" "${files[#]}"

Find a file and copy it to a folder

I'm doing a script that is intended to copy a file to another directory based on a given file path as input. Problem is that it copies the whole folder but the file I'm trying to copy. I tried different options and commands but the result is the same. I'll appreciate your help.
The file I'm trying to copy is "12345.xml"
My code
First, script looks for string "may2017" on a zip folder name. Displaying a list of zipped folder names that matches pattern, then it will look for the file "12345" on each folder list, so the final result will be only one matching zipped folder. Then, the desired result will be to copy the xml file.
find "/path/SourceFolder" -name "*may2017*" -exec grep -l "12345" /dev/null {} + | xargs -I % cp % "/path/TargetFolder"
This is the actual output when running the following commands ( find "/path/SourceFolder" -name "*may2017*" -exec grep -l "12345" /dev/null {} +):
Actual Output
/path/SourceFolder/Folder_may2017
Desired Output
/path/SourceFolder/Folder_may2017/12345.xml

Batch convert PNGs to individual PDFs while maintaining deep folder hierarchy in bash

I've found a solution that claims to do one folder, but I have a deep folder hierarchy of sheet music that I'd like to batch convert from png to pdf. What do my solutions look like?
I will run into a further problem down the line, which may complicate things. Maybe I should write a script? (I'm a total n00b fyi)
The "further problem" is that some of my sheet music spans more than one page, so if the script can parse filenames that include "1of2" and "2of2" to be turned into a single pdf, that'd be neat.
What are my options here?
Thank you so much.
Updated Answer
As an alternative, the following should be faster (as it does the conversions in parallel) and also able to handle larger numbers of files:
find . -name \*.png -print0 | parallel -0 convert {} {.}.pdf
It uses GNU Parallel which is readily available on Linux/Unix and which can be simply installed on OSX with homebrew using:
brew install parallel
Original Answer (as accepted)
If you have bash version 4 or better, you can use extended globbing to recurse directories and do your job very simply:
First enable extended globbing with:
shopt -s globstar
Then recursively convert PNGs to PDFs:
mogrify -format pdf **/*.png
You can loop over png files in a folder hierarchy, and process each one as follows:
find /path/to/your/files -name '*.png' |
while read -r f; do
g=$(basename "$f" .png).pdf
your_conversion_program <"$f" >"$g"
done
To merge pdf-s, you could use pdftk. You need to find all pdf files that have a 1of2 and 2of2 in their name, and run pdftk on those:
find /path/to/your/files -name '*1of2*.pdf' |
while read -r f1; do
f2=${f1/1of2/2of2} # name of second file
([ -f "$f1" ] && [ -f "$f2" ]) || continue # check both exist
g=${f1/1of2//} # name of output file
(! [ -f "$g" ]) || continue # if output exists, skip
pdftk "$f1" "$f2" output "$g"
done
See:
bash string substitution
Regarding a deep folder hierarchy you may use find with -exec option.
First you find all the PNGs in every subfolder and convert them to PDF:
find ./ -name \*\.png -exec convert {} {}.pdf \;
You'll get new PDF files with extension ".png.pdf" (image.png would be converted to image.png.pdf for example)
To correct extensions you may run find command again but this time with "rename" after -exec option.
find ./ -name \*\.png\.pdf -exec rename s/\.png\.pdf/\.pdf/ {} \;
If you want to delete source PNG files, you may use this command, which deletes all files with ".png" extension recursively in every subfolder:
find ./ -name \*\.png -exec rm {} \;
if i understand :
you want to concatenate all your png files from a deep folders structure into only one single pdf.
so...
insure you png are ordered as you want in your folders
be aware you can redirect output of a command (say a search one ;) ) to the input of convert, and tell convert to output in one pdf.
General syntax of convert :
convert 1.png 2.png ... global_png.pdf
The following command :
convert `find . -name '*'.png -print` global_png.pdf
searches for png files in folders from cur_dir
redirects the output of the command find to the input of convert, this is done by back quoting find command
converts works and output to pdf file
(this very simple command line works fine only with unspaced filenames, don't miss quoting the wild char, and back quoting the find command ;) )
[edit]Care....
be sure of what you are doing.
if you delete your png files, you will just loose your original sources...
it might be a very bad practice...
using convert without any tricky -quality output option could create an enormous pdf file... and you might have to re-convert with -quality "60" for instance...
so keep your original sources until you do not need them any more

bash: moving files to original directory based on filename?

I've got a bunch of subdirectories with a couple thousand PNG files that will be sent through Photoshop, creating PSD files. Photoshop can only output those to a single folder, and I want to move each one back to their original directory - so the new file foo_bar_0005.psd should go to where foo_bar_0005.png already is. Every filename only exists once.
Can somebody help me with this? I'm on OSX.
You might start from this minimal script:
#!/bin/bash
search_dir="search/png/from/this/directory/"
psd_dir="path/to/psd/directory/"
for psd_file in "$psd_dir"*.psd; do
file_name="$(echo $psd_file | sed 's/.*\/\(.*\).psd$/\1/g')"
png_dir="$(find $search_dir -name $file_name.png | grep -e '.*/' -o)"
mv $psd_file $png_dir
done
But note that this script doesn't include any error handlers e.g. file collision issue, file not found issue, etc.
Each file found with this find is piped to a Bash command that successively make the psd conversion and move the .psd to the .png original directory.
psd_dir=/psd_dir/
export psd_dir
find . -type f -name '*.png' | xargs -L 1 bash -c 'n=${1##*/}; echo photoshop "$1" && echo mv ${psd_dir}${n%.png}.psd ${1%/*}/; echo' \;
The echo are here to give you an overview of the result.
You should remove them to launch the real photoshop command.

How can I run a bash in every subfolder of a base folder

I want to 'optimize' all my *.png images and found this so I made the bash as it says with:
#!/bin/bash
pngnq -vf -s1 *.png
rename -f 's/-nq8.png$/.png/' *.png
optipng -o7 *.png
And here I have 2 problems:
The first one is that the second line (rename) does nothing... it is supposed to change all the images named [name]-nq8.png which is the result of the first line of the bash to the original name
The second and main problem is: I have a folder named ImagesFolder and inside I have other folders with more *.pngs and I want to run this bash in every subfolder of ImagesFolder but I don't know how to do it (I'm new in unix and shellscripts and so on) and what I tried didn't work or was a mess...
To understand it better what I have is something like:
ImagesFolder
|-Folder1
| |- Folder12
| | |-20 images here
| |- Folder13
| | |- 10 images more here
| |- 5 images here
|-more images
And I want the script to run from ImagesFolder
Thank you so much!
In general, the tool you want to use when you wish to do something recursively on a directory tree is find. If your script is named foo,
find /path/of/base/dir -type f -name '*.png' -exec foo {} \;
will invoke the script on every regular file in the directory tree whose name ends in .png.
What I would probably do is:
1) Fix the script so it takes args instead of the globbing in the current directory:
#!/bin/bash
pngnq -vf -s1 "$1"
mv "${1%.png}-nq8.png" "$1"
optipng -o7 "$1"
2) Test it that it works as intended
3) Run it with find and xargs in parallel (I bet you have a multicore processor)
find . -name '*.png' -print0 | xargs -0 -P6 -n1 the_script
The script could be inline too. But my main point its, use parallelism if you're on multicore. It will speed things up a lot.

Resources