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
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' \;
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
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.
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
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' {} \;