How to delete unused org-mode attachment files from disc - emacs

In org-mode, after deleting a lot of headlines that have had attachment files, the unrefereced files now remain on the disc in my data subdirectory.
Is there a function or script that finds all unrefereced files and does a cleanup?

I faced the same problem today after messing with org-capture-templates and then deleting a bunch of entries that did not come out the way I wanted.
I wrote down this script, which gets the job done (for me).
#!/bin/sh
## Location where org-mode stores attachments
datadir="$HOME/Dropbox/Documents/Org/data";
orgdir="$HOME/Dropbox/Documents/Org/"
echo "The following files appear orphaned:";
files=$(find "$datadir" -type f|perl -ne 'print "$1\n" if /([^\/]*)\/[^\/]*$/'|uniq|while read id; do grep -qiR --include "*.org" "$id" "$orgdir" || find "$datadir" -ipath "*$id*" -type f; done)
echo "$files"
if [ "" == "$files" ]; then
echo "Nothing to do!"
exit
fi
echo "Delete? y/[n]"
read delete
case $delete in
y)
echo "$files" |
while read fn; do
rm "$fn";
done
echo "Done."
;;
*)
echo "Not deleting anything!"
;;
esac

Related

How to change encoding of files in batch

I have tons of files encoded in Japanese (Shift JIS) and I have to change the encoding of them to UTF-8
With VSCode, or some other editors such as Sublime, Emacs, I can open those files with encoding Shift JIS and then save them with encoding UTF-8.
How to change encoding of all files under a folder, including subfolders?
Here is the shell script:
function encode()
{
iconv -f shift_jis -t utf-8 "$1" > test
# iconv -f iso8859-15 -t utf8 "$1" > test;
cat test > "$1";
}
function walk()
{
for file in `ls $1`
do
local path=$1"/"$file
if [ -d $path ]
then
echo "DIR $path"
walk $path
else
echo "FILE $path"
encode $path
fi
done
}
if [ $# -ne 1 ]
then
echo "USAGE: $0 TOP_DIR"
else
walk $1
fi

how to send input to a daemon in linux

#!/bin/bash
. /etc/init.d/functions
NAME=foo
DIR=/home/amit/Desktop
EXEC=foo.pl
PID_FILE=/var/run/foo.pid
IEXE=/etc/init.d/foo
RUN_AS=root
if [ ! -f $DIR/$EXEC ]
then
echo "$DIR/$EXEC not found."
exit
fi
case "$1" in
start)
echo -n "Starting $NAME"
cd $DIR
/home/amit/Desktop/foo.pl
echo "$NAME are now running."
;;
stop)
echo -n "Stopping $NAME"
kill -TERM `cat $PID_FILE`
rm $PID_FILE
echo "$NAME."
;;
force-reload|restart)
$0 stop
$0 start
;;
submit)
echo $2 >> /tmp/jobs
;;
*)
echo "Use: /etc/init.d/$NAME {start|stop|restart|force-reload}"
exit 1
;;
esac
exit 0
i have created a daemon with start and stop options(service foo start/stop) and it works fine. Now I want to send an input to the dameon. something like "service foo submit [argument]" . I want to to know - if user types "service foo submit alexander" , how alexander can be sent to the running daemon ?
If I get the question right - just as you already use positional var $1 you can supply the rest of the arguments to the command as well, i.e.:
"your_start_up_script" [switch to the script as $1] [arg 2 will be accessible via $2] [arg 3 will be accessible via $3]
Then inside script you do:
case "$1" in
start)
echo -n "Starting $NAME"
cd $DIR
/home/amit/Desktop/foo.pl "$2" "$3"

Multiple jar file introspection

How do write a command on bash shell that can search a number of jar files in a directory for a specified class or string path. Eg
I want to search all workshop.jar searching for this string path:
com/bea/workshop/common/util/fileio/ManifestUtil
try this:
find . -name *.jar -exec bash -c "echo {} && jar tvf {} | grep ServiceMBean " \;
Good luck,
-M
Find jars with containing pattern (class or file) create the following script findjars from the root directory of a search tree
#!/bin/bash
JAR=$JAVA_HOME/bin/jar
if [ $# -ne 1 ];
then
echo "Usage: $0 pattern"
exit 1
fi
pattern=`echo $1 | sed -e 's/\./\//g'`
echo "Searching for: [$pattern]"
if [ ! -e $JAR ];
then
echo "$JAR does not exist"
exit 1
fi
for file in `find . -type f \( -name "*.jar" -o -name "*.zip" \) -print`;
do
$JAR tvf $file 2>/dev/null | grep ${pattern} 2>/dev/null
if [ $? -eq 0 ];
then
echo $file
fi
done
and use it as
findjars com/bea/workshop/common/util/fileio/ManifestUtil
Alternatively, to list all classes and files within all of the jar files within a directory or directory tree:
#!/bin/bash
JAR=$JAVA_HOME/bin/jar
if [ ! -e $JAR ];
then
echo "$JAR does not exist"
exit 1
fi
for file in `find . -type f \( -name "*.jar" -o -name "*.zip" \) -print`;
do
echo $file
$JAR tvf $file 2>/dev/null
done
Use JarScan.
Usage: java -jar jarscan.jar [-help | /?]
[-dir directory name]
[-zip]
[-showProgress]
<-files | -class | -package>
<search string 1> [search string 2]
[search string n]

How to strip characters within a filename?

I am having trouble on stripping characters within a filename.
For example:
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
This is the output I want:
1326847080_MUNDO-1.xml
1326836220_PLANETACNN-3.xml
for i in *.xml
do
j=$(echo $i | sed -e s/-.*-/-/)
echo mv $i $j
done
or in one line:
for i in *.xml; do echo mv $i $(echo $i | sed -e s/-.*-/-/); done
remove echo to actually perform the mv command.
Or, without sed, using bash builtin pattern replacement:
for i in *.xml; do echo mv $i ${i//-*-/-}; done
rename to the rescue, with Perl regular expressions. This command will show which moves will be made; just remove -n to actually rename the files:
$ rename -n 's/([^-]+)-.*-([^-]+)/$1-$2/' *.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml renamed as 1326836220_PLANETACNN-3.xml
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml renamed as 1326847080_MUNDO-1.xml
The regular expression explained:
Save the part up to (but excluding) the first dash as match 1.
Save the part after the last dash as match 2.
Replace the part from the start of match 1 to the end of match 2 with match 1, a dash, and match 2.
sorry for the late reply , but i saw it today :( .
I think you are looking for the following
input file ::
cat > abc
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
code : (its a bit too basic , even for my liking)
while read line
do
echo $line ;
fname=`echo $line | cut -d"-" -f1`;
lfield=`echo $line | sed -n 's/\-/ /gp' | wc -w`;
lname=`echo $line | cut -d"-" -f${lfield}`;
new_name="${fname}-${lname}";
echo "new name is :: $new_name";
done < abc ;
output ::
1326847080_MUNDO-Cinco-Cosas-Que-Aprendimos-Del-Debate-De-Los-Republicanos-1.xml
new name is :: 1326847080_MUNDO-1.xml
1326836220_PLANETACNN-Una-Granja-De-Mariposas-Ayuda-A-Reducir-La-Tala-De-Bosques-En-Tanzania-3.xml
new name is :: 1326836220_PLANETACNN-3.xml

Renaming and Moving Files in Bash or Perl

HI, I'm completely new to Bash and StackOverflow.
I need to move a set of files (all contained in the same folder) to a target folder where files with the same name could already exist.
In case a specific file exists, I need to rename the file before moving it, by appending for example an incremental integer to the file name.
The extensions should be preserved (in other words, that appended incremental integer should go before the extension). The file names could contain dots in the middle.
Originally, I was thinking about comparing the two folders to have a list of the existing files (I did this with "comm"), but then I got a bit stuck. I think I'm just trying to do things in the most complicated possible way.
Any hint to do this in the "bash way"? It's OK if it is done in a script other than bash script.
If you don't mind renaming the files that already exist, GNU mv has the --backup option:
mv --backup=numbered * /some/other/dir
Here is a Bash script:
source="/some/dir"
dest="/another/dir"
find "$source" -maxdepth 1 -type f -printf "%f\n" | while read -r file
do
suffix=
if [[ -a "$dest/$file" ]]
then
suffix=".new"
fi
# to make active, comment out the next line and uncomment the line below it
echo 'mv' "\"$source/$file\"" "\"$dest/$file$suffix\""
# mv "source/$file" "$dest/$file$suffix"
done
The suffix is added blindly. If you have files named like "foo.new" in both directories then the result will be one file named "foo.new" and the second named "foo.new.new" which might look silly, but is correct in that it doesn't overwrite the file. However, if the destination already contains "foo.new.new" (and "foo.new" is in both source and destination), then "foo.new.new" will be overwritten).
You can change the if above to a loop in order to deal with that situation. This version also preserves extensions:
source="/some/dir"
dest="/another/dir"
find "$source" -maxdepth 1 -type f -printf "%f\n" | while read -r file
do
suffix=
count=
ext=
base="${file%.*}"
if [[ $file =~ \. ]]
then
ext=".${file##*.}"
fi
while [[ -a "$dest/$base$suffix$count$ext" ]]
do
(( count+=1 ))
suffix="."
done
# to make active, comment out the next line and uncomment the line below it
echo 'mv' "\"$source/$file\"" "\"$dest/$file$suffix$count$ext\""
# mv "$source/$file" "$dest/$file$suffix$count$ext"
done
As per OP, this can be Perl, not just bash. Here we go
NEW SOLUTION: (paying attention to extension)
~/junk/a1$ ls
f1.txt f2.txt f3.txt z1 z2
~/junk/a1$ ls ../a2
f1.txt f2.1.txt f2.2.txt f2.3.txt f2.txt z1
# I split the one-liner into multiple lines for readability
$ perl5.8 -e
'{use strict; use warnings; use File::Copy; use File::Basename;
my #files = glob("*"); # assume current directory
foreach my $file (#files) {
my $file_base2 = basename($file);
my ($file_base, $ext) = ($file_base2 =~ /(.+?)([.][^.]+$)?$/);
my $new_file_base = "../a2/$file_base";
my $new_file = $new_file_base . $ext;
my $counter = 1;
while (-e $new_file) {
$new_file = "$new_file_base." . $counter++ . $ext;
}
copy($file, $new_file)
|| die "could not copy $file to $new_file: $!\n";
} }'
~/junk/a1> ls ../a2
f1.1.txt f1.txt f2.1.txt f2.2.txt f2.3.txt f2.4.txt f2.txt f3.txt
z1 z1.1 z2
OLD SOLUTION: (not paying attention to extension)
~/junk/a1$ ls
f1 f2 f3
~/junk/a1$ ls ../a2
f1 f2 f2.1 f2.2 f2.3
# I split the one-liner into multiple lines for readability
$ perl5.8 -e
'{use strict; use warnings; use File::Copy; use File::Basename;
my #files = glob("*"); # assume current directory
foreach my $file (#files) {
my $file_base = basename($file);
my $new_file_base = "../a2/$file_base";
my $new_file = $new_file_base;
my $counter = 1;
while (-e $new_file) { $new_file = "$new_file_base." . $counter++; }
copy($file,$new_file)
|| die "could not copy $file to $new_file: $!\n";
} }'
~/junk/a1> ls ../a2
f1 f1.1 f2 f2.1 f2.2 f2.3 f2.4 f3
I feel bad for posting this without testing it. However it is late and I have work in the morning. My attempt would look something like this:
## copy files from src to dst
## inserting ~XX into any name between base and extension
## where a name collision would occur
src="$1"
dst="$2"
case "$dst" in
/*) :;; # absolute dest is fine
*) dst=$(pwd)/$dst;; # relative needs to be fixed up
esac
cd "$src"
find . -type f | while read x; do
x=${x#./} # trim off the ./
t=$x; # initial target
d=$(dirname $x); # relative directory
b=$(basename $x); # initial basename
ext=${b%%.*}; # extension
b=${b##*.}; # basename with ext. stripped off
let zz=0; # initial numeric
while [ -e "$dst/$t" ]; do
# target exists, so try constructing a new target name
t="$d/$bb~$zz.$ext"
let zz+=1;
done
echo mv "./$x" "$dst/$t"
done
Overall the strategy is to get each name from the source path, break it into parts, and, for any collision, iterate over names of the form "base~XX.extension" until we find one that doesn't collide.
Obviously I have prepended the mv command with an echo because I'm a coward. Remove that at your own (files') peril.
If you dont need incremental suffix, rsync can do the job:
rsync --archive --backup --suffix=.sic src/ dst
Update:
find/sed/sort is used to manage versioned backup files:
#!/bin/bash
src="${1}"
dst="${2}"
if test ! -d "${src}" -o ! -d "${dst}" ;then
echo Usage: $0 SRC_DIR DST_DIR >&2
exit 1
fi
rsync --archive --backup "${src}/" "${dst}/"
new_name() {
local dst=$1
local prefix=$2
local suffix=$3
local max=$(find ${dst} -type f -regex ".*${prefix}.[0-9]*.${suffix}\$" \
| sed 's/.*\.\([0-9]*\)\..*/\1/'|sort -n|tail -n 1)
let max++
echo ${prefix}.${max}.${suffix}
}
# swap BACKUP-extension/real-extension
for backup_file in $(find $dst -name "*~"); do
file=${backup_file%~}
prefix=${file%.*}
suffix=${file##*.}
suffix=${suffix%\~}
mv ${backup_file} $(new_name $dst $prefix $suffix)
done