linux find no such file or directory but exists - linux

Then i trying to use this script
for line in `cat dirs.txt`;
do
find "$line" -type f \( -name '*good*' -o -exec grep -F "badbad" {} \; \) -exec echo {} \;;
done
I get error on each existing dirs and match the find criteria
find: /home/goods/ : No such file or directory
find: /home/bads/ : No such file or directory
find: /home/fill/ : No such file or directory
But then i look manualy this dirs exist and i can read them all
Why this happens?

You must check in file for ^M$
You can do that with command cat dirs.txt -vET
Then you must trim them all with command cat dirs.txt|tr -d "\r" >1.txt

Issue is that you have dos (^M) line endings, in the file. Running dos2unix dirs.txt dirs.txt should solve the problem. Ideally, you also shouldn't use for line in $(cat ..., but something like
while IFS= read -r line; do
find "$line" -type f \( -name '*good*' -o -exec grep -F "badbad" {} \; \) -exec echo {} \;
done < dirs.txt

Related

How to rename multiple files at once

I have lots of files, directories and sub-directories at my file system.
For example:
/path/to/file/test-poster.jpg
/anotherpath/my-poster.jpg
/tuxisthebest/ohyes/path/exm/bold-poster.jpg
I want to switch all file names from *-poster.jpg to folder.jpg
I have tried with sed and awk with no success.
little help?
You can do it with find:
find -name "*poster.jpg" -exec sh -c 'mv "$0" "${0%/*}/folder.jpg"' '{}' \;
Explanation
Here, for each filename matched, executes:
sh -c 'mv "$0" "${0%/*}/folder.jpg"' '{}'
Where '{}' is the filename passed as an argument to the command_string:
mv "$0" "${0%/*}/folder.jpg"
So, at the end, $0 will have the filename.
Finally, ${0%/*}/folder.jpg expands to the path of the old filename and adds /folder.jpg.
Example
Notice I'm replacing mv with echo
$ find -name "*poster.jpg" -exec sh -c 'echo "$0" "${0%/*}/folder.jpg"' '{}' \;
./anotherpath/my-poster.jpg ./anotherpath/folder.jpg
./path/to/file/test-poster.jpg ./path/to/file/folder.jpg
./tuxisthebest/ohyes/path/exm/bold-poster.jpg ./tuxisthebest/ohyes/path/exm/folder.jpg
Try this script, it should rename all the files as required.
for i in $(find . -name "*-poster.jpg") ; do folder=`echo $i | awk -F"-poster.jpg" {'print $1'}`; mv -iv $i $folder.folder.jpg; done
You can replace . to the directory where these files are placed in the command find . -name "*-poster.jpg" in the script. Let me know if it is working fine for you.
you can try it like
find -name '*poster*' -type f -exec sh -c 'mv "{}" "$(dirname "{}")"/folder.jpg' \;
find all files containing poster == find -name '*poster*' -type f
copy the directory path of the file and store it in a temporary variable and afterwards affix "folder.jpg" to directory path == -exec sh -c 'mv "{}" "$(dirname "{}")"/folder.jpg' \;

Find files in multiple directories taken from list in a file?

FreeBSD 9.2 RELEASE p2
I have a file fromdirs.txt. In this file is a new line separated directory list like so:
/etc
/home
/home/goods/
I need to first find in all directory's files which have names like "good" or contain string "(NODES_'TASK')" and then copy all these files into the directory /tmp.
2.sh file chmod +x and is 755
fromDirs.txt file chmod +x and is 755
This code give me error
IFS=$'\n' read -d '' -r -a dirs < fromDirs.txt
find "${dirs[#]}" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;
2.sh: cannot open fromDirs.txt : No such file or directory
2.sh: ${dirs[...}: Bad substitution
But File fromDirs.txt exist and 2.sh running from it allocation directory, also i trying to provide full path instead of fromDirs.txt and error the same
This code give me error
FILE=fromDirs.txt
IFS='\n'
while read -r dirs
do
find "$dirs" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;
done < "$FILE"
2.sh: 6: Syntax error: "done" unexpected (expecting "do")
This code give me error too
FILENAME=fromDirs.txt
awk '{kount++;print kount, $0}
END{print "\nTotal " kount " lines read"}' $FILENAME
2.sh: : not found awk: can't open file fromDirs.txt source line number 2
So how to read file line by line and do what i need?
This works for me
for line in "`cat fromDirs.txt`"; do find "$line" -type f \( -name '*good*' -o -exec grep -F "(NODES_'TASK')" {} \; \) -exec cp {} /tmp/ \;; done

Recursively prepend text to file names

I want to prepend text to the name of every file of a certain type - in this case .txt files - located in the current directory or a sub-directory.
I have tried:
find -L . -type f -name "*.txt" -exec mv "{}" "PrependedTextHere{}" \;
The problem with this is dealing with the ./ part of the path that comes with the {} reference.
Any help or alternative approaches appreciated.
You can do something like this
find -L . -type f -name "*.txt" -exec bash -c 'echo "$0" "${0%/*}/PrependedTextHere${0##*/}"' {} \;
Where
bash -c '...' executes the command
$0 is the first argument passed in, in this case {} -- the full filename
${0%/*} removes everything including and after the last / in the filename
${0##*/} removes everything before and including the last / in the filename
Replace the echo with a mv once you're satisfied it's working.
Are you just trying to move the files to a new file name that has Prepend before it?
for F in *.txt; do mv "$F" Prepend"$F"; done
Or do you want it to handle subdirectories and prepend between the directory and file name:
dir1/PrependA.txt
dir2/PrependB.txt
Here's a quick shot at it. Let me know if it helps.
for file in $(find -L . -type f -name "*.txt")
do
parent=$(echo $file | sed "s=\(.*/\).*=\1=")
name=$(echo $file | sed "s=.*/\(.*\)=\1=")
mv "$file" "${parent}PrependedTextHere${name}"
done
This ought to work, as long file names does not have new line character(s). In such case make the find to use -print0 and IFS to have null.
#!/bin/sh
IFS='
'
for I in $(find -L . -name '*.txt' -print); do
echo mv "$I" "${I%/*}/prepend-${I##*/}"
done
p.s. Remove the echo to make the script effective, it's there to avoid accidental breakage for people who randomly copy paste stuff from here to their shell.

Possible to grep and modify/touch the file modification date?

I am using the following to find all instances of a string in a number of files and delete the line where they are found.
find . -maxdepth 1 -xdev -type f -exec sed -i '/teststring/Id' {} \;
I don't want to change the date the file was modified because that impacts on the order that the files are shown in an unrelated application. So I was thinking I could grab the date before executing sed, then touch the file and replace the old modify date at the end of the command. I want to have it all in one command integrated with the above if possible.
Try the following command:
find . -maxdepth 1 -xdev -type f -exec sed -i.bak '/teststring/Id' {} \; -exec touch -r {}.bak {} \; -exec rm {}.bak \;
The find command executes three steps for each file found:
sed changes the file and creates a backup of the original file (with a .bak extension)
touch sets the timestamp of the new file to be the same as the backup
rm deletes the backup
for file in $(find . -maxdepth 1 -xdev -type f )
do
mod_time=$(stat --format=%y $file)
perl -wpl -i -e 's!teststring!!' $file
touch -d ''$mod_time'' $file
done

dos2unix command

I have this script
#!/bin/sh
for i in `ls -R`
do
echo "Changing $i"
fromdos $i
done
I want to remove "^M" charcaters from many files which are in more subdirectories. I got this:
fromdos: Unable to access file
Is there somethig i'm missing?
Thanks in advance.
ls -R lists everything, including directories. So you're telling fromdos to act on actual directories is some cases.
Try something like this:
find . -type f -exec fromdos {} \;
I guess you don't need a for loop.
Here is a quick panorama of solutions for files with extension ".ext" (such commands shall be somehow restrictive)
note : ^M is obtained with CTRL-V" + "CTRL-M"
# PORTABLE SOLUTION
find /home -type f -name "*.ext" -exec sed -i -e 's/^M$//' {} \;
# GNU-sed
find /home -type f -name "*.ext" -exec sed -i -e "s/\x0D$//g" {} \;
# SED with more recent nux
find /home -type f -name "*.ext" -exec sed -i -e "s/\r$//g" {} \;
# DOS2UNIX
find /home -type f -name "*.ext" -print0 | while read -r -d "$(printf "\000")" -r path; do dos2unix $path $path"_new"; done
# AWK
find /home -type f -name "*.ext" -print0 | while read -r -d "$(printf "\000")" -r path; do awk '{ sub("\r$", ""); print }' $path > $path"_new"; done
# TR
find /home -type f -name "*.ext" -print0 | while read -r -d "$(printf "\000")" -r path; do cat $path | tr -d '\r' > $path"_new"; done
# PERL
find /home -type f -name "*.ext" -exec perl -pi -e 's/\r//g' {} \;

Resources