echo multi-line string to a file - echo

How can I create a .gitignore file and add:
/node_modules
.DS_Store
.env
all in one command line?
I know I can do this: echo ".DS_Store" >> .gitignore

The classic way to do this is using a HEREDOC (see man bash)
cat - <<EOF >> .gitignore
/nodemodules
.DS_Store
.env
EOF

echo "
/node_modules
.DS_Store
.env" >> .gitignore

I usually use printf, which allows me to write a oneliner:
printf "%s\n" "/node_modules" ".DS_Store" ".env" >> .gitignore

Related

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.

Using results from grep to write results line by line with sed

I am trying to take every file name in a directory that has the extension .text
and write it to a file in that same directory line by line starting at line number 14.
This is what I have so far but doesn't work.
cp workDir | grep -r --include *.text | sed -i '14i' home.text
Any assistance is appreciated. Note: I am on Unix.
You can do the above task by following shell command:
find workDir -name "*.text" >> home.text
This will solve what you have commented.
cp workDir doesn't work, because cp is for copying like cp source destination. Further explanations about cp can be read with man cp.
To achieve your goal go to your directory with cd ~/path/to/workDir. There you can use the ls command and redirect the output appending to your existing file with >> for all .text file extensions.
For example like this:
ls *.text >> home.text
This will append only the filenames line by line to your home.text without a preceding ./ like in the answer bevor with the find command.
Let me know If you like another format for your file names you want to append.

Change package mode of JCR Package

Is there a way to change the packaging mode of an existing JCR package from replace to update? As far as I know the packaging mode cannot be set in the AEM Package Manager dialogs.
What exactly would I have to do? Just change the filter.xml and repackage? Somehow, this didn't work for me. Am I missing something?
You'd have to change the filter.xml as well as the .content.xml in the definition subfolder.
Here is a small batchscript that unpacks, changes the mode and repacks a package.
If you save it as modPkg, you cann call it with two params:
modPkg FILENAME FITLERMODE
where FILENAME is the filename of the package and FILTERMODE should be merge, update or replace.
#!/bin/bash
filename=${1}
filterMode=${2}
echo "Extracting package."
jar xf $1
echo "Modifying filter.xml."
perl -pe 's|(root="[^\"]+")(( )*mode="[^\"]+"( )*)?(( )*(/)?>)|\1 mode="'"${filterMode}"'"\5|g' META-INF/vault/filter.xml > META-INF/vault/filter.xml.backup
rm -rf META-INF/vault/filter.xml
mv META-INF/vault/filter.xml.backup META-INF/vault/filter.xml
echo "Modifying .content.xml in definition-folder."
perl -pe 's|mode="[^\"]+"|mode="'"${filterMode}"'"|g' META-INF/vault/definition/.content.xml > META-INF/vault/definition/.content.xml.backup
rm -rf META-INF/vault/definition/.content.xml
mv META-INF/vault/definition/.content.xml.backup META-INF/vault/definition/.content.xml
echo "Repackaging."
jar -cfM ${filterMode}-${filename} META-INF jcr_root
echo "Deleting temp files."
rm -rf META-INF
rm -rf jcr_root
echo "Finished."
There might be more elegant ways to do the job, but it's easy enough.

comparing two directories with separate diff output per file

I'd need to see what has been changed between two directories which contain different version of a software sourcecode. While I have found a way to get a unique .diff file, how can I obtain a different file for each changed file in the two directories? I'd need this, as the "main" is about 6 MB and wanted some more handy thing.
I came around this problem too, so I ended up with some lines of a shell script. It takes three arguments: Source and destination directory (as used for diff) and a target folder (should exist) for the output.
It's a bit hacky, but maybe it would be useful for someone. So use with care, especially if your paths have special characters.
#!/bin/sh
DIFFARGS="-wb"
LANG=C
TARGET=$3
SRC=`echo $1 | sed -e 's/\//\\\\\\//g'`
DST=`echo $2 | sed -e 's/\//\\\\\\//g'`
if [ ! -d "$TARGET" ]; then
echo "'$TARGET' is not a directory." >&2
exit 1
fi
diff -rqN $DIFFARGS "$1" "$2" | sed "s/Files $SRC\/\(.*\?\) and $DST\/\(.*\?\) differ/\1/" | \
while read file
do
if [ ! -d "$TARGET/`dirname \"$file\"`" ]; then
mkdir -p "$TARGET/`dirname \"$file\"`"
fi
diff $DIFFARGS -N "$1/$file" "$2/$file" > "$TARGET"/"$file.diff"
done
if you want to compare source code it is better to commit it to a source vesioning program as "svn".
after you have done so. do a diff of your uploaded code and pipe it to file.diff
svn diff --old svn:url1 --new svn:url2 > file.diff
A bash for loop will work for you. The following will diff two directories with C source code and produce a separate diff for each file.
for FILE in $(find <FIRST_DIR> -name '*.[ch]'); do DIFF=<DIFF_DIR>/$(echo $FILE | grep -o '[-_a-zA-Z0-9.]*$').diff; diff -u $FILE <SECOND_DIR>/$FILE > $DIFF; done
Use the correct patch level for the lines starting with +++

DOS to UNIX path substitution within a file

I have a file that contains this kind of paths:
C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c
And I would like to get the following file:
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
Note that the non matching path should not be modified.
I know how to do this with sed for a fixed number of subdir, but a variable number is giving me trouble. Actually, I would have to use many s/x/y/ expressions (as many as the max depth... not very elegant).
May be with awk, but this kind of magic is beyond my skills.
FYI, I need this trick to correct some gcov binary files on a cygwin platform.
I am dealing with binary files; therefore, I might have the following kind of data:
bindata\bindata%bindataC:\good\foo.c
which should be translated as:
bindata\bindata%bindataC:/good/foo.c
The first \ must not be translated, despite that it is on the same line.
However, I have just checked my .gcno files while editing this text and it looks like all the paths are flanked with zeros, so most of the answers below should fit.
sed -e '/^C:\\good/ s/\\/\//g' input_file.txt
I would recommend you look into the cygpath utility, which converts path names from one format to another. For instance on my machine:
$ cygpath `pwd`
/home/jericson
$ cygpath -w `pwd`
D:\root\home\jericson
$ cygpath -m `pwd`
D:/root/home/jericson
Here's a Perl implementation of what you asked for:
$ echo 'C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c' | perl -pe 's|\\|/|g if /good/'
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
It works directly with the string, so it will work anywhere. You could combine it with cygpath, but it only works on machines that have that path:
perl -pe '$_ = `cygpath -m $_` if /good/'
(Since I don't have C:\good on my machine, I get output like C:goodfoo.c. If you use a real path on your machine, it ought to work correctly.)
You want to substitute '/' for all '\' but only on the lines that match the good directory path. Both sed and awk will let you do this by having a LHS (matching) expression that only picks the lines with the right path.
A trivial sed script to do this would look like:
/[Cc]:\\good/ s/\\/\//g
For a file:
c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar
You will get the output below:
c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar
Here's how I would do it in awk:
# fixpaths.awk
/C:\\good/ {
gsub(/\\/,"/",$1);
print $1 >> outfile;
}
Then run it using the command:
awk -f fixpaths.awk paths.txt; mv outfile paths.txt
Or with some help from good ol' Bash:
#!/bin/bash
cat file | while read LINE
do
if <bad_condition>
then
echo "$LINE" >> newfile
else
echo "$LINE" | sed -e "s/\\/\//g" >> newfile
fi
done
try this
sed -re '/\\good\\/ s/\\/\//g' temp.txt
or this
awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt