How to print only folder names where same name of file exists - linux

I am trying to write a script where all matching file names exist.
For example, I have a file TEST123 in many subfolders under /opt . I have a list of file names. So, I need to print only folder names which has the same file name .
Desired output :
TEST123
/opt/test2
/opt/test3
I am not sure how to use grep command :
I have a list "elements.txt" with full path of file names. And I cutted only the filenames at the end to " onlyfile.txt" .
This is how elements.txt look with many different file names, some of them has duplicated and some dont.
/opt/test2/TEST123
/opt/test3/TEST123
/opt/test2/TEST577
/opt/test6/SUNNY
/opt/test8/SUNNY
This is onlyfile.txt:
TEST123
TEST577
SUNNY
and many more files
And need to loop with the filename , like
for item in `cat onlyfile.txt`
do
grep elements.txt
done
It is giving me all outputs, but I need only folder names .
Any help would be appreciated.!

To get the directory of every file named TEST123, use the find command:
find /opt -name TEST123 -printf "%h\n"
The output will be:
/opt/test2
/opt/test3
The %h specifier will output the directory of the file. See the find manpage for more information.

In this case i think you need more than one loop.
for item in `cat onlyfile.txt`; do
for path in `cat elements.txt |grep $item`; do
dirname $path
done
done
First loop iterate filenames
Second loop searches filenames in paths and strip file name from them

Related

How to get a folder name in linux bash from a directory

There will be directory which will have any number folder and may be files, I just need pick one random folder and need to process it ( move the folders , etc ..) I need process folder one by one. Need to ignore if there is any files.
I am tiring with below code able to get folder name but , seems there some hidden character or some thing which not giving proper output.
PROCESSING_FOLDER_NAME= ls -l /ecom/bin/catalogUpload/input/TNF-EU/ | grep '^d' | cut -d ' ' -f23 | head -1
#PROCESSING_FOLDER_NAME= echo $PROCESSING_FOLDER_NAME | tr -d '\n\r'
#PROCESSING_FOLDER_NAME=${PROCESSING_FOLDER_NAME%$'\n'}
#echo "PROCESSING_FOLDER_NAME is/$PROCESSING_FOLDER_NAME "
echo "/ecom/bin/catalogUpload/input/TNF-EU/$PROCESSING_FOLDER_NAME/"
output
Thanks_giving_Dec_08
/ecom/bin/catalogUpload/input/TNF-EU//
I am expecting the output should be /ecom/bin/catalogUpload/input/TNF-EU/Thanks_giving_Dec_08/
Here is my bash version.
GNU bash, version 4.2.50(1)-release (powerpc-ibm-aix6.1.2.0)
I mainly need the folder name (not full path) in variable, As the folder name which is processing need be use for emails to notify other, etc.
To get a random folder from a list of folders,
first put the list of folders in an array:
list=(/ecom/bin/catalogUpload/input/TNF-EU/*/)
Next, get a random index using the $RANDOM variable of the shell,
modulo the size of the list:
((index = RANDOM % ${#list[#]}))
Print the value at the selected index:
echo "${list[index]}"
To get just the name of the directory without the full path, you can use the basename command:
basename "${list[index]}"
As for what's wrong with the original script:
To store the result of a command in a variable, the syntax is name=$(cmd) instead of name= cmd
Do not parse the output of ls, it's not reliable
To get directories in a directory, you can use glob patterns like * ending with /, as in the above example */.

Move multiple files from a folder to list of directories (Undo a move command)

I want to undo a move command that I did by moving back all the files in a folder ("MySourceDir") to corresponding paths specified in a .txt file ("ListOfFilePaths.txt).
For eg.:
MySourceDir
File1.txt
File2.txt
File3.txt
.
.
.
I have a text file containing the file paths for each of these files, indicating the directories they were originally in and thus, need to be moved back to.
ListOfFilePaths.txt
/path/to/dirA/File1.txt
/path/to/dirB/File2.txt
/path/to/dirC/File3.txt
I could probably do this in two ways. Write a loop to 1) grep the directory path for each file and then move it to the corresponding grepped directory path OR 2) remove the "File#.txt" portion from the directory path and then do a mv command for each file in the list such that the nth file is moved to the nth directory.
In either case I'm not familiar with writing loops in bash, so any help would be much appreciated!
(Similarly, would also appreciate a command to copy these files back to the original folder instead of moving them, keeping the timestamp unchanged :-) )
From what I understand, you need to:
Loop through the text file
Get the line, extract the text after the final slash (to give you the file name)
Get the destination dir from the line
Copy the file from the source dir to the dest dir
The code below should help:
while read line; do
fileName=$(basename $line)
dirName=$(dirname $line)
cp SourceDir/"$fileName" "$dirName"
done < ListOfFilePaths.txt
basename extracts the filename from a file path.
dirname extracts the dir from a file path.
References:
https://ss64.com/bash/dirname.html
https://linux.die.net/man/1/basename

Merge Files and Prepend Filename and Directory

I need to merge files in a directory and include the directory, filename, and line number in each line of the output. I've found many helpful posts about including the filename and line number but not the directory name. Grep -n gets line numbers and I've seen some find commands that get some of the other parts but I can't seem to pull them all together. (I'm using Ubuntu for all of the data processing.)
Imagine two files in directory named "8". (Each directory in the data I have is a number. The data were provided that way.)
file1.txt
JohnPaulGeorgeRingo
file2.txt
MickKeefBillBrianCharlie
The output should look like this:
8:file1.txt:1:John8:file1.txt:2:Paul8:file1.txt:3:George8:file1.txt:4:Ringo8:file2.txt:1:Mick8:file2.txt:2:Keef8:file2.txt:3:Bill8:file2.txt:4:Brian8:file2.txt:5:Charlie
The separators don't have to be colons. Tabs would work just fine.
Thanks much!
If it's just one directory level deep you could try something like so. We go into each directory, print each line with its number and then append the directory name to the front with sed:
$ for x in `ls`; do
(cd $x ; grep -n . *) | sed -e 's/^/'$x:'/g'
done
1:c.txt:2:B
1:c.txt:3:C
2:a.txt:1:A
2:a.txt:2:B

Bash script to get all file with desired extensions

I'm trying to write a bash script that if I pass a text file containing some extension and a folder returns me an output file with the list of all files that match the desired extension, searching recursively in all sub-directories
the folder is my second parameter the extension list file my first parameter
I have tried:
for i in $1 ; do
find . -name $2\*.$i -print>>result.txt
done
but doesn't work
As noted from in comment:
It is not a good idea to write to a hard coded file name.
The given example fixes only the given code from the OP question.
Yes of course, it is even better to call with
x.sh y . > blabla
and remove the filename from the script itself. But my intention is not to fix the question...
The following bash script, named as x.sh
#!/bin/bash
echo -n >result.txt # delete old content
while read i; do # read a line from file
find $2 -name \*.$i -print>>result.txt # for every item do a find
done <$1 # read from file named with first arg from cmdline
with an text file named y with following content
txt
sh
and called with:
./x.sh y .
results in a file result.txt which contents is:
a.txt
b.txt
x.sh
OK, lets give some additional hints as got from comments:
If the results fiel should not collect any other conntent from other results of the script it can be simplified to:
#!/bin/bash
while read i; do # read a line from file
find $2 -name \*.$i -print # for every item do a find
done <$1 >result.txt # read from file named with first arg from cmdline
And as already mentioned:
The hard coded result.txt could be removed and the call can be something like
./x.sh y . > result.txt
Give this one-liner command a try.
Replace /mydir with the folder to search.
Change the list of extensions passed as argument to the egrep command:
find /mydir -type f | egrep "[.]txt|[.]xml" >> result.txt
After the egrep, each extension should be separated with |.
. char must be escaped with [.]

Imgopt can't optimize file with whitespace in the name

Hy,
I'm trying to optimize the uploaded pictures on my webserver, with imgopt. The problem is that, when it finds a file with whitespace in the name, it throw error like that:
$imgopt file - name.jpg
stat: cannot stat 'file': No such file or directory
stat: cannot stat 'name.jpg': No such file or directory
Can anyone help me please?
Thanks, Dave.
You can still use 'imgopt' but you'll have to rename your files with a command like this:
find your_folder -depth -name "* *" -execdir rename 's/ /_/g' "{}" \;
See the source for more details about renaming directories, etc...
Second answer: you can also pass file names with spaces with a command like this (source):
for fname in "$#"; do
process-one-file-at-a-time "$fname"
done
You're actually passing three options to the imgopt program :
file
-
name.jpg
The program probably treats each one of them as a separate file name (with - being stdin, following the standard Unix convention) and tries to open them. This, of course, fails. What you want are quotes :
imgopt "file - name.jpg"
This way, only one argument is given to the program and it contains a valid filename, with all the whitespace-y goodness.

Resources