"Spoof" File Extension In Bash - linux

Is there a way to "spoof" the file extension of a file in bash for consumption by another program? I can think of doing some shell scripting and making lots of soft-links, but that isn't very scalable.
Let's imagine I have a program I'm trying to use that requires input files to be of a specific file extension, and it has no method of turning off this check.

You could make a fifo with the requisite extension and cat any other file type into it. So, if your crazy program needs to see files that end in .funky, you can do this:
mkfifo file.funky
cat someotherfile > file.funky &
someprogram file.funky

Create a symbolic link for each file you want to have a particular extension, then pass the name of the symlink to the command.
For example suppose you have files with names of the form *.foo and you need to refer to them with extensions of .bar:
for file in *.foo ; do
ln -s $file _$$_$file.bar
done
I precede each symlink name with _$$_ to avoid the possibility of colliding with an existing file name (you don't want to do ln -s file.foo file.bar if file.bar already exists).
With a little more programming, your script can keep track of which symlinks it created and, if you like, clean them up after executing the command.
This assumes, as you stated in the question, that the command can't be forced to accept a different extension.
You could, without too much difficulty, create a wrapper script that replaces the command in question, creating the symlinks, invoking the command, and cleaning up after itself automatically.

Related

Empty log files daily using cron task

I want to empty (not delete) log files daily at a particular time. something like
echo "" > /home/user/dir/log/*.log
but it returns
-bash: /home/user/dir/log/*.log: ambiguous redirect
is there any way to achieve this?
You can't redirect to more than one file, but you can tee to multiple files.
tee /home/user/dir/log/*.log </dev/null
The redirect from /dev/null also avoids writing an empty line to the beginning of each file, which was another bug in your attempt. (Perhaps specify nullglob to avoid creating a file with the name *.log if the wildcard doesn't match any existing files, though.)
However, a much better solution is probably to use the utility logrotate which is installed out of the box on every Debian (and thus also Ubuntu, Mint, etc) installation. It runs nightly by default, and can be configured by dropping a file in its configuration directory. It lets you compress the previous version of a log file instead of just overwrite, and takes care to preserve ownership and permissions etc.

How to execute .sh file which is in jar file

I have jar file in some location.(/test/lib/myproject.jar).
In that jar file, I have .sh file (/org/com/api/demo.sh).
Now I want to execute that demo.sh file.
How can I execute that file in Linux/Unix?
You can use unzip to extract the file, and pipe it to sh to run it.
unzip -p /test/lib/myproject.jar org/com/api/demo.sh |
sh
Notice how zip files generally cannot contain absolute paths. The first argument to unzip is the archive and the remaining arguments name the archive members to extract; the -p option says to extract to standard output.
As a special case, if you need to execute the code in the context of the current shell (i.e. effectively source it) this is one of the rare cases where wrapping a command in $(...) makes sense. (Many beginners like to try to put this in all kinds of weird places.)
$(unzip -p /test/lib/myproject.jar org/com/api/demo.sh)
You should prefer the first option unless you specifically know that you need the second, and understand the difference. Also, as usual, you should only execute code you trust, and, ideally, have vetted.
If you need to run the code more than once, save it to a file and mark it as executable.
unzip -p /test/lib/myproject.jar org/com/api/demo.sh >demo
chmod +x ./demo
and then to run it
./demo

Bash - cat in a hidden . file or write to it

Let's say I make a file .history.txt:
touch .history.txt
and I try to write to it:
cat > .history.txt
after having done that all I get is:
bash: .history.txt: is a directory
What I need is to be able to write some text to it like I would be able to any normal file. Any ideas what am I doing wrong?
A file doesn't need to already exist in order to redirect output to it (the shell will create the file if necessary). But Bash is telling you that .history.txt already exists and is a directory, so you can't write to it.
You either need to remove the existing directory rm -rf .history.txt or use a different file name. Then cat > .whatever.txt should work on its own.

SVN Pre-commit Symbolic Link Path in Perl

In my workplace, there's one Perl script that runs on a Unix machine every time someone tries to check-in a file to the SVN repo for any of the 10-20 projects.
The way it works is that each project has its own "Hooks" folder with a file called "pre-commit" which SVN automatically executes when someone check-in something. Except the "pre-commit" file is actually a symbolic link to the one central Perl script common to all projects just so that if a change needs to be made to the Perl script it doesn't need to be done for every project.
So my problem is this: I need to put a text file in each of these projects' "hooks" directory, each one containing some settings specific to that project. So there will be 10-20 settings files (one per project) each in their respective "hooks" directory.
The problem is that I need to open these text files in the Perl script and read from them but I'm having issues letting Perl know where to find it. I tried using the $0 parameter which is supposed to tell me where the script is being executed from but because it's a symbolic link it just says "Not a directory" and the script terminates. I need to get the path of the "hooks" directory so that I can find the text file.
The SVN pre-commit script is supposed to be invoked with the path to the repository as its first argument. Inside a Perl script, that argument should be available as $ARGV[0]. You should be able to build the path to the corresponding hooks directory or to a file inside that directory by simply appending to the repository path, like this:
$repopath = $ARGV[0];
$hookspath = $repopath . "/hooks";
$myfilepath = $hookspath . "/myfile";
although for maximum portability it would be cleaner to use the pathname-manipulation functions in the File::Spec module to do this.
If this approach doesn't work then you'll have to explain more about how your Perl script gets invoked. For instance, if your pre-commit script is really a shell script wrapper that eventually invokes perl then perhaps it's not passing the pre-commit arguments along properly.
Showing us your current code that's failing would be a good thing too.

Inject parameter in hardcoded tar command

I'm using a linux software solution that uses the tar command to backup huge amounts of data.
The command which is hardcoded into the binary which calls the tar is:
/bin/tar --exclude "/backup" --exclude / --ignore-failed-read -cvjf - /pbackup 2>>'/tar_err.log' | split -b 1000m - '/backup/temp/backup.tar.bz2'
There is no chance to change the command, as it is harcoded. It uses bzip2 to compress the data. I experienced a strong performance improvement (up to 60%) when using the parameter --use-compress-prog=pbzip2 which utilizes all CPU cores.
By symlinking the bzip2 from /bin/bzip2 to the pbzip2 binary I tried to trick the software, however when monitoring the process it still uses bzip2 as I tink this is built into tar.
I know it is a tricky question but is there any way to utilize pbzip2 without changing this command that is externally called?
My system is Debian Sequeeze.
Thanks very much!
Danger: ugly solution ahead; backup the binary before proceeding
First of all, check if the hardcoded string is easily accessible: use strings on your binary, and see if it displays the string you said (probably it will be in several pieces, e.g. /bin/tar, --exclude, --ignore-failed-read, ...).
If this succeeds, grab your hex editor of choice, open the binary and look for the hardcoded string; if it's split in several pieces, the one you need is the one containing /bin/tar; overwrite tar with some arbitrary three-letter name, e.g. fkt (fake tar; a quick Google search didn't turn up any result for /usr/bin/fkt, so we should be safe).
The program should now call your /usr/bin/fkt instead of the regular tar.
Now, put in your /bin a script like this:
#!/bin/sh
/bin/tar --use-compress-prog=pbzip2 $*
call it with the name you chose before (fkt) and set the permissions correctly (they should be 755 and owned by root). This script just takes all the parameters it gets and call the real tar, adding in front of them the parameter you need.
Another solution, that I suggested in the comments, may be creating a chroot just for the application, renaming tar to some other name (realtar, maybe?) and calling the script above tar (obviously now you should change the /bin/tar inside the script to /bin/realtar).
If the program is not updated very often and the trick worked at the first try I would probably go with the first solution, setting up and maintaining chroots is not fun.
Why not move /bin/tar to (say) /bin/tar-original
Then create a script /bin/tar to do whatever you want it to do.

Resources