Diff without files - diff

Is it possible to use the "diff" tool without having physical files? Something like this:
diff "hello" "hell"

You can diff standard input with a file by using the special filename -:
# diff the contents of the file 'some-file' with the string "foobar"
echo foobar | diff - some-file
With bash, you can also use anonymous named pipes (a bit of a misnomer) to diff two pipelines:
# diff the string "foo" with the string "baz"
diff <(echo foo) <(echo baz)
See also How can you diff two pipelines with bash?.

Related

Cat in sh file doesn't echo empty lines [duplicate]

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 2 years ago.
The file myfile.sh looks like this:
echo "hello"
The file I run looks like this:
a=$(cat myfile.sh)
echo $a
When I run the file, I only get the output:
echo "hello"
And not what the actual file content is. What's going on here?
http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html
In a=$(cat myfile.sh) your variable gets assigned
the standard output of the command, with any trailing newlines deleted
And that is where your extra lines went.
From the man page for dash (/bin/sh) on my system,
The shell expands the command substitution by executing command in a subshell environment and replacing the command substitution with the standard output of the command, removing sequences of one or more ⟨newline⟩s at the end of the substitution. (Embedded ⟨newline⟩s before the end of the output are not removed; however, during field splitting, they may be translated into ⟨space⟩s, depending on the value of IFS and quoting that is in effect.)
(Emphasis mine.)
You could use the following:
#!/bin/sh
LF='
'
a=
while read -r line; do
a="$a$line$LF"
done
printf -- '--\n%s--' "$a"
Test:
$ printf 'a b c\nd\n\n\ne\n\n\n' | ./a.sh
--
a b c
d
e
--

How can I convert indentation between spaces and tabs for all files in a workspace in a single action?

How can I use VS Code's Convert Indentation To Spaces or Convert Indentation to Tabs commands on all the files in my workspace in a single action instead of using the command for each file?
I'm not aware of a way to do this with VS Code (at least- not without extensions, and I don't know of any such extensions offhand).
But if you're on a posix system (not sure if I'm using "posix" right here), you can do this via command line using a modified version of this:
git ls-files | command grep -E '*.ts$' | awk '{print "expand --tabs=4 --first-only", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
The above command lists all files tracked in the git repo for the current working directory, filters for files with the .ts extension, and then uses awk and expand to replace leading indentation of a tabs to a specified number of spaces.
To go from spaces to tabs, use the unexpand command instead.
If you're not working with a git repo, you can replace git ls-files with find -type f (the advantage of git ls-files is that it won't touch anything that's not tracked).
Just change the regular expression in the grep filter to whatever you need.
The command replaces leading groups of 4 spaces with tab characters. Just change the --tabs argument to the unexpand command with whatever number of spaces your indentation is.

How to pass a variable to the mv command to rename a file text with spaces and the variable's text in a bash (.sh) file

I create a variable and store the day, date & time in it:
NOW=$(date "+%a %d/%m/%Y% %H:%M")
Then I would like to pass $NOW to the mv command to rename a file.
e.g. Create file named a.txt with a title and the current date:
printf "File Report (" > ~/Desktop/a.txt
echo $NOW"):\n" >> ~/Desktop/a.txt
Then I try to rename the file with the variable ($NOW) included in the name:
mv ~/Desktop/a.txt ~/Desktop/'File Report $NOW'.txt
What should that last line be? I also tried these two options.
mv ~/Desktop/a.txt ~/Desktop/'File Report' $NOW.txt
&
mv ~/Desktop/a.txt ~/Desktop/'File Report'${NOW}.txt
Assuming a reasonably Bourne-like shell (such as bash), variable substitution does not happen inside single quotes. You need to use double quotes:
mv ~/Desktop/a.txt "${HOME}/Desktop/File Report ${NOW}.txt"
(I'm not sure whether the curly braces are required, but they can't hurt)
You will also need to change the date command to avoid the use of slashes. For example:
NOW="$(date '+%a %d-%m-%Y% %H:%M')"

Rename multiple files from command line [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Renaming lots of files in Linux according to a pattern
I have multiple files in this format:
file_1.pdf
file_2.pdf
...
file_100.pdf
My question is how can I rename all files, that look like this:
file_001.pdf
file_002.pdf
...
file_100.pdf
I know you can rename multiple files with 'rename', but I don't know how to do this in this case.
You can do this using the Perl tool rename from the shell prompt. (There are other tools with the same name which may or may not be able to do this, so be careful.)
rename 's/(\d+)/sprintf("%03d", $1)/e' *.pdf
If you want to do a dry run to make sure you don't clobber any files, add the -n switch to the command.
note
If you run the following command (linux)
$ file $(readlink -f $(type -p rename))
and you have a result like
.../rename: Perl script, ASCII text executable
then this seems to be the right tool =)
This seems to be the default rename command on Ubuntu.
To make it the default on Debian and derivative like Ubuntu :
sudo update-alternatives --set rename /path/to/rename
Explanations
s/// is the base substitution expression : s/to_replace/replaced/, check perldoc perlre
(\d+) capture with () at least one integer : \d or more : + in $1
sprintf("%03d", $1) sprintf is like printf, but not used to print but to format a string with the same syntax. %03d is for zero padding, and $1 is the captured string. Check perldoc -f sprintf
the later perl's function is permited because of the e modifier at the end of the expression
If you want to do it with pure bash:
for f in file_*.pdf; do x="${f##*_}"; echo mv "$f" "${f%_*}$(printf '_%03d.pdf' "${x%.pdf}")"; done
(note the debugging echo)

Organizing my papers in org-mode

I've just started using org-mode, and so far find it quite useful. I have a very large collection of technical papers in a directory tree, and I'd like to go through them and index them through org-mode. What I'd like is to have a way of going through them and look at the unannotated ones, and annotate them one by one. I imagine doing this by first making up a file of links like [[xxx.pdf][not done yet]], and then being presented with the not done ones, glancing at them and deciding how what annotations to put in. In addition I'd like to add tags. What I'd really like is to be able to make up new tags on the fly. Has anyone done anything like this in org-mode?
Victor
If you have your papers organized like this,
% ls -1 ~/References/functional-programming
The Lambda Calculus.pdf
Recursive Functions of Symbolic Expressions and Their.pdf
you can run a quick script to build an org-file. Save the following as make-org and run it from your directory of papers (sh make-org > papers.org).
#! /bin/sh
#
# make-org -- generates an org-mode file from a directory of PDFs
#
# AUTHOR:
# Jon-Michael Deldin
# USAGE:
# cd ~/path/to/papers && make-org > papers.org
#
echo "#+TITLE: Research Papers"
echo "#+STARTUP: align hidestars indent lognotedone"
echo
for f in *.pdf; do
name=${f%.*} # strip extension
path=$(echo $f | sed 's/ /%20/') # encode spaces as %20
echo "* TODO $name :unread:"
echo
echo "[[file:$path][$name]]"
echo
done
Open papers.org in Emacs, run C-u C-c C-q to realign the tags. Your file should now look like this:
In addition I'd like to add tags. What I'd really like is to be able to make up new tags on the fly.
Once you have a headline (thing with * at the beginning, you can hit C-c C-c and add any tag you want.
You may find this detailed write-up of using org-mode and RefTeX or this alternate approach useful, especially if you use LaTeX.
Heres is the modified version that works on a directory.
#! /bin/sh
#
# make-org -- generates an org-mode file from a directory of PDFs
#
# AUTHOR:
# Jon-Michael Deldin
# USAGE:
# cd ~/path/to/papers && make-org > papers.org
#
echo "#+TITLE: Research Papers"
echo "#+STARTUP: align hidestars indent lognotedone"
echo
for f in $(find . -name '*.pdf'); do
name=${f%.*} # strip extension
path=$(echo $f | sed 's/ /%20/') # encode spaces as %20
echo "* TODO $name :unread:"
echo
echo "[[file:$path][$name]]"
echo
done