Sed * only modifying first file - sed

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

Related

Just trying to delete lines of several .txt files - but keep getting SED error

So, I am trying to delete the first 23 lines of many .txt files. This is what I am currently doing:
sed -i -e 1,23d * .txt
but it gives me a weird error:
sed: 1: "1,23": command expected
I have no idea what to do. _
Like this:
sed -i -e '1,23d' *.txt
# ^ mandatory 'd'
# ^
# no space between * and .txt
The original question (before editing) showed:
sed -i -e 1,23d * .txt
but it gives me a weird error:
sed: Applications: in-place editing only works for regular files
The space between * and .txt was a mistake, but is an explanation of the weird error: It looks for all files as well as for the hidden file .txt.
Linux considers the directory Application as a file, but sed does not work on files.
The directory Application suggests that the files might come from Windows.
Another question is why echo *.txt don't show the txt files Mia was expecting. A logical explanation is that the files originated from Windows and Mia doesn't know that Linux is case sensitive. Files like A.TXT and b.Txt don't match *.txt.
When all txt files end with TXT, you can do
sed -i -e '1,23d' *.TXT
When you have a mix of upper- and lower case, the easiest way is
sed -i -e '1,23d' *.[tT][xX][tT]

sed remove a special control character from many files

Can someone please give me the exact syntax for removing ^# from thousands of html files in nested directories using sed? The ^# is a control character inserted by a windows program that generated these files. I cannot seem to get the syntax right.
I tried this (but it did not work) using a file since I could not enter the control-character at the command prompt:
find ./ *.html -type f -exec sed -i 's/^#//g' {} ;
POSIX sed doesn't handle NUL in input but GNU sed can with hex escape:
find . -name '*.html' -type f -exec sed -i 's/\x0//g' '{}' +

How to rename all the files (without for loop) in a single line command?

I want to rename all the files in my home directory (example abc), in the format (abc_bkp) without using any loops and it should be a single line command in unix (bash script).
If the directory contains nothing but files, this should do it:
ls | xargs -I {} mv {} {}_bkp
If it contains subdirectories, links, and other things you don't want to rename, you must filter the output of ls. Here is a crude way to do it; maybe someone can suggest a more elegant approach:
ls -l | grep ^- | cut -d' ' -f 13 | xargs -I {} mv {} {}_bkp
If you don't want to use loops then I believe the BEST way could be find command, try following command as a DRY run first and once you are satisfy with results then you could remove echo from it to give a real shot.
find -type f -or -type d | xargs -I % echo mv % %_bkp
-I: From man xargs page:
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not
terminate
input items; instead the separator is the newline character. Implies -x and -L 1.

sed over multiple files in multiple directories

I have the following directory tree:
books>book(i)>cluster.pir
where book(i) are a set of sub directories 1 to 1023 each containing a folder called cluster.pir.
The following sed command:
sed -i '/>/d' ./*.pir
will delete any line in the file containing '>' for any file with a .pir ext, which is great, but my various .pir files are located in their own book(i) directory. How do I get the command to span across all the directories? I have tried:
find ./*.pir -type f -exec sed -i '/>/d' ./*.pir
when starting in the 'book' parent directory, but I get:
find: missing argument to `-exec'
does anyone have any thoughts on this?
Thanks.
The format for find is:
find -exec command {} \;
Where {} is replaced by the filename.
Edit: In your case this would become:
find ./*.pir -type f -exec sed -i '/>/d' {} \;
This will call sed on every file.
You can add a wildcard to span all directories:
sed -i '/>/d' ./book*/*.pir
I was having trouble using file wild-cards with sed on my Mac and this method worked fine:
FILE_PATH="/some/path/"
sed -i '' "s|search|replace|g" $(find ${FILE_PATH} -name '*.ext')

unix find and replace text in dir and subdirs

I'm trying to change the name of "my-silly-home-page-name.html" to "index.html" in all documents within a given master directory and subdirs.
I saw this: Shell script - search and replace text in multiple files using a list of strings.
And this: How to change all occurrences of a word in all files in a directory
I have tried this:
grep -r "my-silly-home-page-name.html" .
This finds the lines on which the text exists, but now I would like to substitute 'my-silly-home-page-name' for 'index'.
How would I do this with sed or perl?
Or do I even need sed/perl?
Something like:
grep -r "my-silly-home-page-name.html" . | sed 's/$1/'index'/g'
?
Also; I am trying this with perl, and I try the following:
perl -i -p -e 's/my-silly-home-page-name\.html/index\.html/g' *
This works, but I get an error when perl encounters directories, saying "Can't do inplace edit: SOMEDIR-NAME is not a regular file, <> line N"
Thanks,
jml
find . -type f -exec \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g' {} +
Or if your find doesn't support -exec +,
find . -type f -print0 | xargs -0 \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g'
Both pass to Perl as arguments as many names at a time as possible. Both work with any file name, including those that contains newlines.
If you are on Windows and you are using a Windows build of Perl (as opposed to a cygwin build), -i won't work unless you also do a backup of the original. Change -i to -i.bak. You can then go and delete the backups using
find . -type f -name '*.bak' -delete
This should do the job:
find . -type f -print0 | xargs -0 sed -e 's/my-silly-home-page-name\.html/index\.html/g' -i
Basically it gathers recursively all the files from the given directory (. in the example) with find and runs sed with the same substitution command as in the perl command in the question through xargs.
Regarding the question about sed vs. perl, I'd say that you should use the one you're more comfortable with since I don't expect huge differences (the substitution command is the same one after all).
There are probably better ways to do this but you can use:
find . -name oldname.html |perl -e 'map { s/[\r\n]//g; $old = $_; s/oldname.txt$/newname.html/; rename $old,$_ } <>';
Fyi, grep searches for a pattern; find searches for files.