Redirecting vcftools file in linux - tips - linux

Here is the code that gets the VCF file from a specific region using tabix and then filters it for specific (european) population using 'keep' option from vcftools.
####select specific population
if [ "$POP_FILE" != "" ]; then
vcftools --vcf temp.vcf --keep $POP_FILE --recode --recode-INFO-all > temp2.vcf 2> /dev/null
else
cp -f temp.vcf temp2.vcf
fi
PROBLEM: it creates the recode.vcf file but then the redirection is not happening as the temp2 file is empty

I would avoid vcftools and use bcftools (https://github.com/samtools/bcftools) instead:
if [ "$POP_FILE" != "" ]; then
bcftools view temp.vcf -S $POP_FILE -o temp2.vcf
else
cp -f temp.vcf temp2.vcf
fi
To install bcftools:
git clone --branch=develop git://github.com/samtools/bcftools.git
git clone --branch=develop git://github.com/samtools/htslib.git
cd htslib && make && cd ..
cd bcftools && make && cd ..
sudo cp bcftools/bcftools /usr/local/bin/

Related

is there a touch that can create parent directories like mkdir -p?

I have the following two functions defined in my .zshrc
newdir(){ # make a new dir and cd into it
if [ $# != 1 ]; then
printf "\nUsage: newdir <dir> \n"
else
/bin/mkdir -p $1 && cd $1
fi
}
newfile() { # make a new file, open it for editing, here specified where
if [ -z "$1" ]; then
printf "\nUsage: newfile FILENAME \n"
printf "touches a new file in the current working directory and opens with nano to edit \n\n"
printf "Alternate usage: newfile /path/to/file FILENAME \n"
printf "touches a new file in the specified directory, creating the diretory if needed, and opens to edit with nano \n"
elif [ -n "$2" ]; then
FILENAME="$2"
DIRNAME="$1"
if [ -d "$DIRNAME" ]; then
cd $DIRNAME
else
newdir $DIRNAME
fi
else
FILENAME="$1"
fi
touch ./"$FILENAME"
nano ./"$FILENAME"
}
but I am wondering, is there a version of touch that acts similar to mkdir -p, in that it can create parent dirs as needed in one line/command?
There is no touch that can create parent directory path, so write your own in standard POSIX-shell grammar that also works with zsh:
#!/usr/bin/env sh
touchp() {
for arg
do
# Get base directory
baseDir=${arg%/*}
# If whole path is not equal to the baseDire (sole element)
# AND baseDir is not a directory (or does not exist)
if ! { [ "$arg" = "$baseDir" ] || [ -d "$baseDir" ];}; then
# Creates leading directories
mkdir -p "${arg%/*}"
fi
# Touch file in-place without cd into dir
touch "$arg"
done
}
With zsh you can do:
mkdir -p -- $#:h && : >>| $#
mkdir is given the "head" of each argument to make the directories (man zshexpn says the :h expansion modifier works like the dirname tool). Then, assuming you have not unset the MUTLIOS option, the output of : (a command that produces no output) is appended to the files.

If else with rm Shell linux

I need help whith my problem.
I need make a shell script...
this it's my idea
if [ rm -r -f /directorie ]; then
code
else
code
fi
...
how I can?
dir=/directory
test -d "${dir}" && rm -rf "${dir}" && ! test -d "${dir}" && echo OK || echo NOK
This code may achieve what you want:
#!/bin/bash
rm -r /directorie > /dev/null 2>&1; rc="$?"
if [ "$rc" -eq "0" ]; then
# code here
else
# code here
fi
Note: rm -rf /directorie (with the option f) would always return a return code = 0 (true), thus it is not suited for an if test.
Edit: this answer can be condensed into a bash one-liner:
rm -r /home/owner/scripts > /dev/null 2>&1 && code here (true) || code here (false)

Combine & with && shell

I have this shell script in a php file:
[ ! -e "dsaasdas3efsdgadd345y5erhaha45_temp" ] && touch dsaasdas3efsdgadd345y5erhaha45_temp && wget http://localmyurltofunction?id=100 -O ./images/100 > /dev/null 2>&1 && rm dsaasdas3efsdgadd345y5erhaha45_temp &
I tested that in shell without the last & and it works great, but when I add the last & won't run, returning 1. I need a way to combine && with my &, I use that & because I want this process to run in background on a separate fork compared to my script.
You probably want to run the entire list in the background, not just the rm command.
( [ ! -e foo ] && touch foo && wget ... && rm foo ) &

Recycle Bin in Bash Script

I am trying to create a basic recycle bin concept in a VM using bash scripting. It will need to delete files that have been entered and place them into a directory that is created and save the path(origin) to a log file to be later used in a restore function.
I will start off with my delete/recycle code which I believe works just fine but seems kind of untidy/contains redundant code:
#!/bin/sh
if [ ! -d ~/recycle ]
then mkdir ~/recycle
fi
if [ ! -d ~/recycle/recycle_log ]
then mkdir ~/recycle/recycle_log
fi
if [ ! -d ~/recycle/recycle_bin ]
then mkdir ~/recycle/recycle_bin
fi
if [ -d ~/recycle ]
then
echo "$(readlink -f "$1")" >> "$HOME/recycle/recycle_log/log_file" && mv "$1" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$2")" >> "$HOME/recycle/recycle_log/log_file" && mv "$2" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$3")" >> "$HOME/recycle/recycle_log/log_file" && mv "$3" "$HOME/recycle/recycle_bin"
echo "$(readlink -f "$4")" >> "$HOME/recycle/recycle_log/log_file" && mv "$4" "$HOME/recycle/recycle_bin"
fi
#end
Thereafter what I have for my restore script is as follows:
#!/bin/sh
cd "$HOME/recycle/recycle_bin" || exit 1
mv -i "$(grep "$1" "$HOME/recycle/recycle_log")"
I imagine this is somewhat close to what I need to return any deleted file stored in the log/recycle bin to be restored to its origin but the error I am getting is:
mv: missing destination file operand after `'
Any thoughts on where I'm going wrong?
Try this:
recycle.sh
#!/bin/sh
set -e
check_dir() {
[ ! -d $1 ] || return 0
mkdir --parents $1
}
check_dir "${HOME}/recycle/recycle_bin"
touch "${HOME}/recycle/recycle_log"
for file in "$#"; do
echo "$(readlink -f "$file")" >> "${HOME}/recycle/recycle_log"
mv "$file" "${HOME}/recycle/recycle_bin"
done
#end
restore.sh
#!/bin/sh
set -e
cd "${HOME}/recycle/recycle_bin" || exit 1
for name in "$#"; do
file=$(grep "\/${name}\$" "${HOME}/recycle/recycle_log")
mv -i $name "$file"
sed -i "/\/${name}\$/ d" "${HOME}/recycle/recycle_log"
done
Some insights:
set -e: Abort on any error, to avoid some if's
$#: The array of arguments ($1, $2...)
[ ! -d $1 ] || return 0: Since we are using set -e, do not fail if the directory exists
grep "\/${name}\$" ...: Only matches the name at the end of the path
sed -i: sed in-place editing to remove the line

File inside a directory script

I have written a bash script to create a file in the directory name given. The script I wrote was:
D=$2
F=$1
D=`cat > "$F" && mkdir -v "$D"`
When I run the script passing the 2 arguments filename and pathname, it shows the file as being created but when I search for that file it not showing up in that directory.
Your order or creation is wrong, use something like this:
~/temp5$ ls
script1.bash
~/temp5$ cat script1.bash
D=$2
F=$1
mkdir -v "$D" && > "$D/$F"
~/temp5$ ./script1.bash newfilename newdirname
mkdir: created directory ‘newdirname’
~/temp5$ ls
newdirname script1.bash
~/temp5$ ls newdirname/
newfilename
$
This is the final script:
D=$2
F=$1
mkdir -v "$D" && > "$D/$F"
Edit1:
$ ls
script.bash
~/temp5$ cat script.bash
D=$2
F=$1
[[ "$D$F" =~ ^[a-zA-Z0-9]+$ ]] && mkdir -v "$D" && > "$D/$F"
~/temp5$ ./script.bash newfile123 newdir123
mkdir: created directory ‘newdir123’
~/temp5$ ls
newdir123 script.bash
~/temp5$ ls newdir123/
newfile123
~/temp5$ ./script.bash 'newfile;123' newdir123
~/temp5$ ./script.bash newfile.123 newdir123
~/temp5$ ls
newdir123 script.bash
~/temp5$ ls newdir123/
newfile123
$
This is the final script:
D=$2
F=$1
[[ "$D$F" =~ ^[a-zA-Z0-9]+$ ]] && mkdir -v "$D" && > "$D/$F"
[[ "$D$F" =~ ^[a-zA-Z0-9]+$ ]] ensures that both directory and file names have only these(1 or more alphanumeric/numeric) characters: a-z, A-Z and 0-9 using regular expressions.
You order of actions is wrong: you create the file before creating the directory. You should have done something like
mkdir "$D"
chdir "$D"
cat > "$F"
This will create the directory and a blank file of desired name in provided location
mkdir -p $2 && touch $2/$1

Resources