sed incorrectly strips backslashes - c

find . | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/"
Prints out the directory structure of the current directory, which is what I want. Example:
.
|-one
|-two
| |-two_2
| |-two_1
|-test_file
However, when I put it in an alias file (file with all of my aliases), like so:
alias ls_tmp="cd /tmp; find . | sed -e \"s/[^-][^\\/]*\\// |/g\" -e \"s/|\\([^ ]\\)/|-\\1/\""
, which is being loaded with the following sed commands:
// load alias
sprintf(buf, "cat %s|grep \"^alias \"| sed -e \"s/=/ /\" | sed -e \"s/\\\\\\\\//g\"", FILE_NAME);
f = popen(buf, "r");
if (f == NULL) {
fprintf(stderr, "error: failed to init alias commands.\n");
return;
}
, the command actualy executed is actually
cd /tmp; find . | sed -e "s/[^-][^/]*// |/g" -e "s/|([^ ])/|-1/"
Note that all of the backslashes have been stripped, despite the fact that I escaped the backslashes using //.
How do I make this work? I'm confused as to what
sed -e \"s/=/ /\" | sed -e \"s/\\\\\\\\//g
does. Maybe it has to do with the \\\\?

Related

How do we run SED with inline file option while it must have twice or more pipe process

How do we do SED as inline file option on many pipe
sed -i -E ':k /\b("[^"]+"\s*([A-z]\w*\s*)?)+,?\s*$/{N;s/\s*\n\s*/ /;
s/\)\s*;/);\n/; bk}' uci.c \
| sed -E 's/\b\s*("[^%"]+")\s*\)\s*;/c\1;/' | sed -E 's/;/;;/'
and how to do such in batch files by instructing glob uci*.c? Thanks
There are various ways to go about it. If having three separate sed processes is not explicitely needed, you could either combine the three sed scripts into one:
sed -i -E \
':k /\b("[^"]+"\s*([A-z]\w*\s*)?)+,?\s*$/{N;s/\s*\n\s*/ /;
s/\)\s*;/);\n/; bk};s/\b\s*("[^%"]+")\s*\)\s*;/c\1;/;s/;/;;/' \
uci.c
or run sed with multiple script arguments:
sed -i -E \
-e ':k /\b("[^"]+"\s*([A-z]\w*\s*)?)+,?\s*$/{N;s/\s*\n\s*/ /;
s/\)\s*;/);\n/; bk}' \
-e 's/\b\s*("[^%"]+")\s*\)\s*;/c\1;/' \
-e 's/;/;;/' \
uci.c
If you want to keep the pipeline, you'll have to use some kind of temp file, either explicitly:
tmpf="$(mktemp)"
sed -E ':k /\b("[^"]+"\s*([A-z]\w*\s*)?)+,?\s*$/{N;s/\s*\n\s*/ /;
s/\)\s*;/);\n/; bk}' uci.c \
| sed -E 's/\b\s*("[^%"]+")\s*\)\s*;/c\1;/' \
| sed -E 's/;/;;/' > "$tmpf"
mv -f "$tmpf" uci.c
or implicitly, through a uility like sponge (from moreutils):
sed -E ':k /\b("[^"]+"\s*([A-z]\w*\s*)?)+,?\s*$/{N;s/\s*\n\s*/ /;
s/\)\s*;/);\n/; bk}' uci.c \
| sed -E 's/\b\s*("[^%"]+")\s*\)\s*;/c\1;/' \
| sed -E 's/;/;;/' \
| sponge uci.c

Shell script: Sed substitution throwing unknown command: ` '

I'm having some trouble getting around an issue related to performing a sed substitution with array's being passed into it as variables. I'm nearly certain it has something to do with the way I'm passing the variables, but I've been scouring for hours for a solution to no avail.
The arrays are initialized in the first six lines of code before attempting a sed substitution. The full script is below:
#!/bin/bash
scalarLineNums=( $(grep -nr 'MCSTEP\|NCSTEP\|ISAVE\|DCGRAX\|DCGRAY\|DCGRAZ\|DCSTEC\|DCTIME\|ICOUTF\|ICOUTI\|D1PEKS\|D1PEFR\|D1PEPF\|MBCON\|NBCON\|D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ' Layer_Rough.Y3D | cut -d ":" -f 1) )
vectorLineNums=( $(sed -n -e '/D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ/{n;=;p;}' Layer_Rough.Y3D | sed -n 1~2p) )
scalarValuesOriginal=( $(grep -nr 'MCSTEP\|NCSTEP\|ISAVE\|DCGRAX\|DCGRAY\|DCGRAZ\|DCSTEC\|DCTIME\|ICOUTF\|ICOUTI\|D1PEKS\|D1PEFR\|D1PEPF\|MBCON\|NBCON\|D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ' Layer_Rough.Y3D | awk -F ' +' '{print $2}') )
vectorValuesOriginal=( $(sed -n -e '/D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ/{n;=;p;}' Layer_Rough.Y3D | sed -n 2~2p) )
scalarValuesNew=( $(grep -nr 'MCSTEP\|NCSTEP\|ISAVE\|DCGRAX\|DCGRAY\|DCGRAZ\|DCSTEC\|DCTIME\|ICOUTF\|ICOUTI\|D1PEKS\|D1PEFR\|D1PEPF\|MBCON\|NBCON\|D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ' new-variable-list.txt | awk -F ' +' '{print $2}') )
vectorValuesNew=( $(sed -n -e '/D1BNVX\|D1BNVY\|D1BNVZ\|I1BNVX\|I1BNVY\|I1BNVZ\|D1BNFX\|D1BNFY\|D1BNFZ\|D1BNAX\|D1BNAY\|D1BNAZ/{n;=;p;}' new-variable-list.txt | sed -n 2~2p) )
i=0
for linenumber in "${scalarLineNums[#]}"
do
sed -i "${linenumber}s/${scalarValuesOriginal[$i]}/${scalarValuesNew[$i]}/" Layer_Rough.Y3D
i=$((i+1))
done
The error I receive when trying to run the script is
sed: -e expression #1, char 2: unknown command: `
'
The for loop is an attempt to perform a substitution on a per line basis, i.e., sed 'line#s/oldvalue/newvalue/'. A few of the elements contain '+' and '-' characters as some of the values are stored in scientific notation, but do not contain any slashes or whitespace.

How do i find the largest file, by size, then copy to another directory

how do I search for files in a directory, sort by size, then copy the largest file into another directory.
I have seen bits and pieces..yet to solve it.
I have tried the below code. However, it does not work.
find sourceDirectory -type f -exec ls -s {} \; | sort -n -r | head -1 | cp {} targetdirectory
The curly brace notation ({}) is used in the arguments for the -exec option for find, it has no meaning to cp in this context. You need to split this up into two separate steps, 1) find the file, and 2) copy the file.
If you are using GNU find I would suggest something like this:
read size filepath < <(find . -type f -printf '%k %p\n' | sort -nr)
cp "$filepath" target/path/
Here is an alternative that avoids temporary variables:
cp "$(find . -type f -printf '%k %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" target/path/
You can replace -printf '%k %p\n' by-exec ls -s {} \;` but printf is much more efficient.
Note that special precautions may be needed if the file names contain other than ASCII characters.
You were almost there. just needed extra support of awk and xargs
I would prefer using du in place of ls -s although they both work fine in this case.
find <sourceDirectory> -type f -exec du {} \; | sort -nr | head -1 | awk '{print $2}' | xargs -I file cp file <targetdirectory>

How to prevent c from interpreting \s of sed

I'm using below command to remove commented, empty lines from a file and search for a particular pattern.
sed '/#/d' $file | sed '/^[ ]*$/d' | tr -d '\n' | sed -n 's/^.*tags\s*[{]\s*hosttags\s*=\s*\([0-1]\)\s*[}].*/tags {hosttags = \1}/p'
Though the above expression works out to me in shell, I have to use it in C. The problem is in this line.
sprintf(buf, "sed '/#/d' %s | sed '/^[ ]*$/d' | tr -d '\n' | sed -n 's/^.*tags\s*[{]\s*hosttags\s*=\s*\([0-1]\)\s*[}].*/tags {hosttags = \1}/p'",file);
C tries to interpret \s and compiling fails. Replacing \s with [[:space]] is not working.
Please let me know how I can get this working in C.
Double up the backslashes, changing \n to \\n, \s to \\s, and so on:
sprintf(buf, "sed '/#/d' %s | sed '/^[ ]*$/d' | tr -d '\\n' | sed -n 's/^.*tags\\s*[{]\\s*hosttags\\s*=\\s*\\([0-1]\\)\\s*[}].*/tags {hosttags = \\1}/p'",file);
When \\ appears in C string literal, a single backslash is embedded into the string in its place.
Replace \s with the POSIX character class [[:space:]].

Bash: Script for finding files by mime-type

First, I am not experienced in scripting, so be gentle with me
Anyway, I tried making a script for finding files by mime-type ( audio, video, text...etc), and here's the poor result I came up with.
#!/bin/bash
FINDPATH="$1"
FILETYPE="$2"
locate $FINDPATH* | while read FILEPROCESS
do
if file -bi "$FILEPROCESS" | grep -q "$FILETYPE"
then
echo $FILEPROCESS
fi
done
It works, but as you could guess, the performance is not so good.
So, can you guys help me make it better ? and also, I don't want to rely on files extensions.
Update:
Here's what I am using now
#!/bin/bash
FINDPATH="$1"
find "$FINDPATH" -type f | file -i -F "::" -f - | awk -v FILETYPE="$2" -F"::" '$2 ~ FILETYPE { print $1 }'
Forking (exec) is expensive. This runs the file command only once, so it is fast:
find . -print | file -if - | grep "what you want" | awk -F: '{print $1}'
or
locate what.want | file -if -
check man file
-i #print mime types
-f - #read filenames from the stdin
#!/bin/bash
find $1 | file -if- | grep $2 | awk -F: '{print $1}'
#!/usr/bin/env bash
mimetypes=$(sed -E 's/\/.*//g; /^$/d; /^#/d' /etc/mime.types | uniq)
display_help(){
echo "Usage: ${0##*/} [mimetype]"
echo "Available mimetypes:"
echo "$mimetypes"
exit 2
}
[[ $# -lt 1 ]] && display_help
ext=$(sed -E "/^${1}/!d; s/^[^ \t]+[ \t]*//g; /^$/d; s/ /\n/g" /etc/mime.types | sed -Ez 's/\n$//; s/\n/\\|/g; s/(.*)/\.*\\.\\(\1\\)\n/')
find "$PWD" -type f -regex "$ext"

Resources