In TextMate (or Sublime) how can I get the path relative my project directory? - textmate

I've got the absolute path available in commands via $TM_FILEPATH. How can I write a command that gives me a relative path, specifically i'd like to copy this path to enable sharing and ease some git/bash operations?

pbcopy will place a string onto your clipboard. From there, you just need to do some detect and replacement.
Start with the standard bash Command TextMate boilerplate:
#!/usr/bin/env bash
[[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh"
Then check if the $TM_PROJECT_DIRECTORY exists:
if [ -z ${TM_PROJECT_DIRECTORY+x} ]; then
If not, copy the full path:
echo -n "$TM_FILEPATH" | pbcopy
echo "$TM_FILEPATH"'\n Absolute path copied to clipboard'
If so replace the project path in the file path, and copy;
else
TM_PROJECT_DIRECTORY="$TM_PROJECT_DIRECTORY/"
echo -n "${TM_FILEPATH#$TM_PROJECT_DIRECTORY}" | pbcopy
echo "${TM_FILEPATH#$TM_PROJECT_DIRECTORY}"'\n Project relative path copied to clipboard.'
fi;
Please see this gist incase of updates.

Related

How to store absolute path of back up files in log file using bash?

I am working on bash to create a back up system. My code is
#!/bin/bash
if [ ! -d "BackUp" ]
then
mkdir BackUp
fi
echo "enter number of access days you want to take for back up."
read days
bak="$(find . -mtime +$days)"
for file in $bak
do
mv $file BackUp
done
tar -cvf BackUp.tgz BackUp >> backUp.log
So, currently I am only taking log file from tar. so it does not prints the full path it only takes current working directory for text in log file.My last line of code takes up input for log file.
But the path stored is
.BackUp/foo1
.BackUp/foo2
.BackUp/foo3
instead i want it to be
home/ubuntu/Downloads/BackUp/foo1
home/ubuntu/Downloads/BackUp/foo2
home/ubuntu/Downloads/BackUp/foo3
You could store the absolute path in a variable and use it in the tar command:
BackUpDirFullPath=$(cd BackUp && pwd)
As command substitution invokes a subshell you are not leaving the current directory by executing cd.
Update:
In order to make -v output absolute paths (on Mac OS) I had to change to the root directory in a subshell and execute it from there ... something like that:
(cd / && tar -cvf /$OLDPWD/BackUp.tgz $BackUpDirFullPath)
This does output absolute paths ... in order to preserve the leading / you might try -P which preserves path names.

A simple mv command in a BASH script

The aim of my script:
look at all the files in a directory ($Home/Music/TEST) and its sub-directories (they are music files)
find out what music genre each file belongs to
if the genre is Heavy, then move the file to another directory ($Home/Music/Output)
This is what I have:
#!/bin/bash
cd Music/TEST
for files in *
do
if [ -f "$files" ];then
# use mminfo to get the track info
genre=`mminfo "$files"|grep genre|awk -F: '{print $2}'|sed 's/^ *//g'|sed 's/[^a-zA-Z0-9\ \-\_]//g'`
if [ $genre = Heavy ] ;then
mv "$files" "~/Music/Output/$files"
fi
fi
done
Please tell me how to write the mv command. Everything I have tried has failed. I get errors like this:
mv: cannot move ‘3rd Eye Landslide.mp3’ to ‘/Music/Output/3rd Eye Landslide.mp3’: No such file or directory
Please don't think I wrote that mminfo line - that's just copied from good old Google search. It's way beyond me.
Your second argument to mv appears to be "~/Music/Output/$files"
If the ~ is meant to signify your home directory, you should use $HOME instead, like:
mv "$files" "$HOME/Music/Output/$files"
~ does not expand to $HOME when quoted.
By the look of it the problem occurs when you move the file to its destination.Please check that /Music/Output/ exits from your current directory.Alternatively use the absolute path to make it safe. Also it's a good idea not use space in the file-name.Hope this will helps.:)
Put this command before mv command should fix your problem.
mkdir -p ~/Music/Output

Source bash script to another one [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reliable way for a bash script to get the full path to itself?
I have bash script test.sh which use functions from another search.sh script by following lines:
source ../scripts/search.sh
<call some functions from search.sh>
Both scripts are located in git repository. search.sh in <git_root>/scripts/ directory, test.sh is located in the same directory (but, generally speaking, could be located anywhere inside <git_root> directory - I mean I can't rely on the following source search.sh approach ).
When I call test.sh script from <git_root>/scripts/ everything works well, but as soon as I change current working directory test.sh fails:
cd <git_root>/scripts/
./test.sh //OK
cd ..
./scripts/test.sh //FAILS
./scripts/test.sh: line 1: ../scripts/search.sh: No file or directory ...
Thus what I have:
Relative path of search.sh script towards <git_root> directory
What I want: To have ability to run test.sh from anywhere inside <git_root> without errors.
P.S.: It is not possible to use permanent absolute path to search.sh as git repository can be cloned to any location.
If both the scripts are in the same directory, then if you get the directory that the running script is in, you use that as the directory to call the other script:
# Get the directory this script is in
pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd -P`
popd > /dev/null
# Now use that directory to call the other script
source $SCRIPTPATH/search.sh
Taken from the accepted answer of the question I marked this question a duplicatre of: https://stackoverflow.com/a/4774063/440558
Is there a way to identify this Git repository location? An environment variable set? You could set PATH in the script itself to include the Git repository:
PATH="$GIT_REPO_LOCATION/scripts:$PATH"
. search.sh
Once the script is complete, your PATH will revert to its old value, and $GIT_REPO_LOCATION/scripts will no longer be part of the PATH.
The question is finding this location to begin with. I guess you could do something like this in your script:
GIT_LOCATION=$(find $HOME -name "search.sh" | head -1)
GIT_SCRIPT_DIR=$(dirname $GIT_LOCATION)
PATH="$GIT_SCRIPT_DIR:$PATH"
. search.sh
By the way, now that $PATH is set, I can call the script via search.sh and not ./search.sh which you had to do when you were in the scripts directory, and your PATH didn't include . which is the current directory (and PATH shouldn't include . because it is a security hole).
One more note, you could search for the .git directory too which might be the Git repository you're looking for:
GIT_LOCATION=$(find $HOME -name ".git" -type d | head -1)
PATH="$GIT_LOCATION:$PATH"
. search.sh
You could do this:
# Get path the Git repo
GIT_ROOT=`git rev-parse --show-toplevel`
# Load the search functions
source $GIT_ROOT/scripts/search.sh
How get Git root directory!
Or like #Joachim Pileborg says, but you have to pay attention that you must know the path of this one to another script;
# Call the other script
source $SCRIPTPATH/../scripts/search.sh
# Or if it is in another path
source $SCRIPTPATH/../scripts/seachers/search.sh
The Apache Tomcat scripts use this approach:
# resolve links - $0 may be a softlink
PRG="$0"
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
PRGDIR=`dirname "$PRG"`
Any way, you have to put this snippet on all scripts that use other scripts.
For the people who would rather not use git's features for finding the parent directory. If you can be sure you'll always be running the script from within the git directory, you can use something like this:
git_root=""
while /bin/true ; do
if [[ "$(pwd)" == "$HOME" ]] || [[ "$(pwd)" == "/" ]] ; then
break
fi
if [[ -d ".git" ]] ; then
git_root="$(pwd)"
break
fi
cd ..
done
I haven't tested this but it will just loop back until it hits your home directory or / and it will see if there is a .git directory in each parent directory. If there is, it sets the git_root variable and it will break out. If it doesn't find one, git_root will just be an empty string. Then you can do:
if [[ -n "$git_root" ]] ; then
. ${git_root}/scripts/search.sh
fi
IHTH

Getting relative paths in BASH

I already searched for this, but I guess there was no great demand on working with paths.
So I'm trying two write a bash script to convert my music collection using tta and cue files.
My directory structure is as following: /Volumes/External/Music/Just/Some/Dirs/Album.tta for the tta files and /Volumes/External/Cuesheets/Just/Some/Dirs/Album.cue for cue sheets.
My current approach is setting /Volumes/External as "root_dir" and get the relative path of the album.tta file to $ROOT_DIR/Music (in this case this would be Just/Some/Dirs/Album.tta), then add this result to $ROOT_DIR/Cuesheets and change the suffix from .tta to .cue.
My current problem is, that dirname returns paths as they are, which means /Volumes/External/Music/Just/Some/Dirs does not get converted to ./Just/Some/Dirs/ when my current folder is $ROOT_DIR/Music and the absolute path was given.
Add://Here is the script if anybody has similar problems:
#!/bin/bash
ROOT_DIR=/Volumes/External
BASE="$1"
if [ ! -f "$BASE" ]
then
echo "Not a file"
exit 1
fi
if [ -n "$2" ]
then
OUTPUT_DIR="$HOME/tmp"
else
OUTPUT_DIR="$2"
fi
mkfdir -p "$OUTPUT_DIR" || exit 1
BASE=${BASE#"$ROOT_DIR/Music/"}
BASE=${BASE%.*}
TTA_FILE="$ROOT_DIR/Music/$BASE.tta"
CUE_FILE="$ROOT_DIR/Cuesheets/$BASE.cue"
shntool split -f "${CUE_FILE}" -o aiff -t "%n %t" -d "${OUTPUT_DIR}" "${TTA_FILE}"
exit 0
If your Cuesheets dir is always in the same directory as your Music, you can just remove root_dir from the path, and what is left is the relative path. If you have the path to your album.tta in album_path (album_path=/Volumes/External/Music/Just/Some/Dirs/Album.tta) and your root_dir set(root_dir=/Volumes/External), just do ${album_path#$root_dir}. This trims root_dir from the front of album_path, so you are left with album_path=Just/Some/Dirs/Album.tta.
See bash docs for more information on bash string manipulation
EDIT:// Changed ${$album_path#$root_dir} to ${album_path#$root_dir}
Okay so I've tackled this a couple of ways in the past. I don't recommend screwing with paths and pwd environment variables, I've seen some catastrophic events because of it.
Here's what I would do
CURRENTDIR=/Volumes/External/Music # make sure you check the existence in your script
...
SEDVAL=$(echo $CURRENTDIR | sed s/'\/'/'\\\/'/g)
#run your loops for iterating through files
for a in $(find ./ -name \*ogg); do
FILE=`echo $a | sed s/$SEDVAL/./g` # strip the initial directory and replace it with .
convert_file $FILE # whatever action to be performed
done
If this is something you might do frequently I would actually just write a separate script just for this.

Bash script to safely create symlinks?

I'm trying to store all my profile configuration files (~/.xxx) in git. I'm pretty horrible at bash scripting but I imagine this will be pretty straight forward for you scripting gurus.
Basically, I'd like a script that will create symbolic links in my home directory to files in my repo. Twist is, I'd like it warn and prompt for overwrite if the symlink will be overwriting an actual file. It should also prompt if a sym link is going to be overwritten, but the target path is different.
I don't mind manually editing the script for each link I want to create. I'm more concerned with being able to quickly deploy new config scripts by running this script stored in my repo.
Any ideas?
The ln command is already conservative about erasing, so maybe the KISS approach is good enough for you:
ln -s git-stuff/home/.[!.]* .
If a file or link already exists, you'll get an error message and this link will be skipped.
If you want the files to have a different name in your repository, pass the -n option to ln so that it doesn't accidentally create a symlink in an existing subdirectory of that name:
ln -sn git-stuff/home/profile .profile
...
If you also want to have links in subdirectories of your home directory, cp -as reproduces the directory structure but creates symbolic links for regular files. With the -i option, it prompts if a target already exists.
cp -i -as git-stuff/home/.[!.]* .
(My answer assumes GNU ln and GNU cp, such as you'd find on Linux (and Cygwin) but usually not on other unices.)
The following has race conditions, but it is probably as safe as you can get without filesystem transactions:
# create a symlink at $dest pointing to $source
# not well tested
set -e # abort on errors
if [[ ( -h $dest && $(readlink -n "$dest") != $source ) || -f $dest || -d $dest ]]
then
read -p "Overwrite $dest? " answer
else
answer=y
fi
[[ $answer == y ]] && ln -s -n -f -v -- "$source" "$dest"

Resources