Deleting lines from file not matching pattern with sed - sed

I generate a list of everything in a directory (subdirectories and all files) with
ls -R $DIRPATH | awk '/:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }' > filelist
and I would like to delete all files not ending in a certain file extension, for example .h. I am trying this with
sed -ne '/.h$/p' filelist > filelist_h
but this is allowing files like C:/dev/boost/boost_1_59_0/boost/graph. How do I get this working with .h and not h?

find is the tool you are looking for:
find "$DIRPATH" -type f -name '*.h'

Related

Sed * only modifying first file

I would like to delete the first 40 lines of a good number of ASCII files and save the ASCII files without those 40 lines
I'm working under OSX High Sierra, realized that the -i option in sed was not working unless I create a backup file, so I tried using this command:
sed -i'backup' -e '1,40d' *.txt
It however only modifies and deletes the first 40 lines in my first file (alphabetically), but not the others.
How can I edit multiple files with just one command?
Thanks
You can use the following command that will
look in the current folder
ignore sub folder
take only into account files whose filenames end with '*.txt'
before executing the sed command.
Command:
find . -maxdepth 1 -type f -name '*.txt' -exec sed -i 'backup' -e '1,40d' {} \;

SH - Save command with parameter in variable

Im trying make an script which can find and store specific type files in a folder.
When I run myScript.sh:
$ ./myScript.sh *.txt
It should save in files.txt all files with .txt extension but doesn't work for me. Only save first file.
myScript.sh:
var=`find $1`
for file in $var
do
echo $var >> files.txt
done
That's an example for practice
Do it like this:
for file in $#
do
echo "$file" >> files.txt
done
Using $#, you can get all the arguments in the script that you pass.
You don't need a loop at all. Just redirect the output of find to your file.
find . "$1" >> files.txt
Finally, i fix this issue passing .txt instead *.txt and changing my script like this:
$ ./myScript.sh *.txt
var=`find *$1`
for file in $var
do
echo $var >> files.txt
done
It works for me.
Thank you all for answer!
I don't understand why you are passing arguments to the script at all. If you want all the files in the current directory whose name ends in ".txt", you could do either:
ls *.txt > files.txt
or
find . -name '*.txt' > files.txt # descends the directory tree
or (not standard)
find . -maxdepth 1 -name '*.txt' > files.txt
None of these will handle files with embedded newlines particularly well, but that use case is not handled well when storing names in a file.

Find files and delete characters in the filenames

So I have a directory called testdir and I want to delete the underscores in the filenames from the files in that directory.
I tried to use this command
find testdir -type f -exec ls {} \; | sed 's/_*//'
It will output the filenames without the underscores but it won't delete the underscores permanently. Could anyone help me?
Thanks!
If you are just looping through the files in your dir, use a simple loop:
while IFS= read -r file
do
echo mv "$file" "${file//_/}" #once you are sure it works, remove the echo!
done < <(find -type f -name "*_*")
This will feed the while loop with the output of the find command. Then, uses ${var//_/} to remove all _ in the name.
Why wasn't your approach working?
Because you are saying
find ... -exec ls {} \; | sed '...'
That is, you are finding something and then changing the output with sed. That is, nothing is done to the file itself.
This may help you
find testdir -type f | rename 's/_//'
Regards

Files not available after running find command

I tried to rename files ending with ".txt" to ".abc" using the find command as below. Now the files are not available on my disk.
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$1.abc"' {} \;
can someone explain me the above command in detail what is did with the files.
Is there any possibility to retrive those, if yes how ?
You used the wrong variable and most of the files cannot be retrieved.
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$1.abc"' {} \;
will rename every .txt file to a file called .abc. So if you files named bar.txt and foo.txt it will rename bar.txt to .abc and then rename foo.txt to .abc which will overwrite the original contents of bar.txt. You cannot see the file because it is .abc and is hidden under a normal list. If you run 'ls -a' you will see a file named ".abc" which will have the contents of the last .txt file that was renamed.
I am not sure how to do exactly what you wanted but running
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$0.abc"' {} \;
will rename each .txt file to a .txt.abc file. So you would have bar.txt.abc and foo.txt.abc
The explanation of rondo is correct.
But what are the solutions for your problem?
If you want to replace the suffix .txt with .abc you can use rename
You will have success, if you use rename and find like this:
find . -type f -iname '*.txt' -print0 | xargs -0 rename .txt .abc
For all files found by find like x.txt or a/b.txt the appropriate command will execute, e.g.
rename .txt .abc x.txt
rename .txt .abc a/b.txt
so x.txt -> x.abc, and a/b.txt -> a/b.abc
If you only want to add the suffix .abc to all files you can still use mv
find . -type f -iname '*.txt' -print0 | xargs -0 mv {} {}.abc
With xargs for each file the command mv is executed.
BTW: with the find option "-print0" and the xargs option "-0" the commands work also with filenames which includes spaces.

Unix Shell scripting find and replace string in specific files in subfolders

I want to replace the string "Solve the problem" with "Choose the best answer" in only the xml files which exist in the subfolders of a folder. I have compiled a script which helps me to do this, but there are 2 problems
It also replaces the content of the script
It replaces the text in all files of the subfolders( but I want only xml to change)
I want to display error messages(text output preferably) if the text mismatch happens in a particular subfolder and file.
So can you please help me modify my existing script so that I can solve the above 3 problems.
The script I have is :
find -type f | xargs sed -i "s/Solve the problem/Choose the best answer/g"
Using bash and sed:
search='Solve the problem'
replace='Choose the best answer'
for file in `find -name '*.xml'`; do
grep "$search" $file &> /dev/null
if [ $? -ne 0 ]; then
echo "Search string not found in $file!"
else
sed -i "s/$search/$replace/" $file
fi
done
find -type f -name "*.xml" | xargs sed -i "s/Solve the problem/Choose the best answer/g"
Not sure I understand issue 3.