Truncate path and keep only filenames

Hi everyone,

I have a question for you, I'm trying to create a script that will automate creating loading screens for the iPhone.

So what I need to do, is list the directories inside /var/mobile/Applications and scan inside those, for the .app directory inside each. Take that .app name and create a folder in /var/stash/Themes/LoadingScreens.theme/Folders with the same name found earlier.

I tried to get the list with this command:

find /var/mobile/Applications/ -name "*.app"

But what I get is a list with the full path in front of what I need to get. How could I either truncate it to keep only what I need, or either list only the .app directories, and not the full path preceding it?

Thank you in advance,

Pierre-Andr�

If the file name doesn't contain the "/" character, you could use split function in perl.

Try combining man find (POSIX) and man basename (POSIX).

You could pipe the output through sed to strip the path:

find . -name "*.foo" | sed "s!.*/!!"

Well actually the .app name is a directory name.

I was able to shorten the path to: /ThisIsAnApp.app using the following command:

find /var/mobile/Applications/ -name "*.app" | sed 's/\/.*\/.*\/.*\/\(.*\)/\/\1/g'

After looking at another post about truncating here.

While I can follow guides, and stuff, and I'm confortable with linux based system, I don't know the commands in enough details to come up with a solution myself. So just by telling me to look at the split function of perl, wouldnt be enough, but sure a starting point for me to look for.

Here is a concrete example of what exactly I'm trying to do.

If I list my /var/mobile/Applications, I will have a bunch of directories named like this:

026E729E-B9D1-4A7A-B07F-A5DAEA4F2E7E and so on.

Inside each is a few folders, and filenames. But what I want to get is the DoodleJump.app directory name inside that 026E729E-B9D1-4A7A-B07F-A5DAEA4F2E7E folder. Then create a DoodleJump.app folder in /var/stash/Themes/LoadingScreens.theme/Folders directory.

And repeat for every directories inside /var/mobile/Applications.

I hope it's more clear now.. Sorry I'm french, so...

---------- Post updated at 07:01 PM ---------- Previous update was at 06:59 PM ----------

I get this error message with the following line of code:

-sh: !.*/!!": event not found

Seems I misunderstood the original request; this will just strip the paths which I don't think is what is desired.

I can get the list I want with this line of code:

find /var/mobile/Applications/ -name "*.app" -printf "%f\n"

How to process each and create the directories from there? would for dir in something works? How to pipe the lists to the for dir loop?

That's an odd message, but since it wasn't going to do what you need, I'd say let it drop for now. I'm thinking on this; someone else may post some help before I do.

If French is your native language, then your English is great! It wasn't your fault -- I didn't see my misunderstanding until after I had posted.

---------- Post updated at 19:14 ---------- Previous update was at 19:09 ----------

Cool. Then this is an example of how you could make your directories:


find /var/mobile/Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        echo "making directory: $file_name"    # nice confirmation
        mkdir /var/stash/Themes/LoadingScreens.theme/Folders/$file_name
done

If you want to test it before you do any damage, change mkdir to echo, or add echo before mkdir and it will just print what it would do to the screen.

Hope this is finally of some use.

1 Like

Thank you very much! It worked!

This is what I used exactly:

find /var/mobile/Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        echo "making directory $file_name"    # nice confirmation
        mkdir "/var/stash/Themes.X7N9if/iMatte Loading Screens.theme/Folders/$file_name"
done

If I may ask, if I want to give that script to some people, knowing that their Themes.X7N9if will be something else, like Themes.Z49fP (always 5 characters), could I use Themes.????? instead, so it works with everyone?

The problem with using wildcards is if there is more than one matching name it will cause problems on the mkdir command as it will expand to two pathnames.

I would look in /var/stash for Themes directories and if there is just one, use it, and if there is more than one, prompt the user to enter the desired target.

Something like this would work (untested!!)

tmp=/tmp/list.$$
ls -d /var/stash/Themes.* >$tmp 2>/dev/null     # look for existing directories

if [[ -s $tmp ]]     # if tmp file has size, something was found
then
        count=$(wc -l <$tmp)     
        if (( $count > 1 ))
        then
                echo "found more than one Themes directories in /var/stash; please enter path to use:"
                cat $tmp
                read tpath
        else
                read tpath <$tmp                # just get the one path
        fi

        tpath="$tpath/iMatte Loading Screens.theme/Folders"             # build the whole name
else
        echo "could not find a Themes directory in /var/stash [FAIL]"
        exit 1
fi


rm -f $tmp

You then can change your mkdir statement to be:

mkdir "$tpath/$file_name"

Sorry for the long response time -- got distracted.

1 Like

Works flawlessly! You are really good! :slight_smile:

If you don't mind me asking one more thing, but before, here is a little explanation or what I'm trying to do now.

If someone is using my theme, prior to now, all the directories inside the loading screens directories (the .app directories), used to contain only one file, the loading screen, which was basically the same file.

As I added more and more Default.png (the file that goes there), it became clear I had to deal with this some other ways... having more than 500 loading screens, it was a bit more than 50 mb, just for the same file repeating itself.

So I created links instead, pointing to one file. I managed to search the net, and build a small script that removed the Default.png from each dir, and link instead to a Default.png located two folders up.

Now when I run the script on my iphone now, since I already ran it before, I get error messages saying cannot create, cannot link, bla bla bla.. that's normal, and doesn't matter, but would there be a clean way of dealing with this?

Also, would there be a way to determine, if there is a Default.png already there, to remove it (or even better, check if it's size is over a certain amount, like 1kb, so it's not a link but a real image, and if it's over 1kb, remove and link, and if under 1kb, skip it.)

The reason why I'm asking this, is because yesterday, when I first removed all the Default.png image and created links, I used this:

for dir in *;
do [ -d "$dir" ] && rm "$dir/Default.png" && ln -s ../../Default.png "$dir/Default.png" ;
done

And it worked pretty good. Except that when I wanted to add that part to the creating directories script you built me earlier, I ended up with messages saying there are no Default.png to remove, which is expectable(!), but it didn't followed on the linking part. So it worked and removed all the links, and created new ones, but all those that were just created and empty, they were still empty after too, no links got created.

So from now, I'd like to determine if there is already a .app dir in /Folders, if so, check if there is a Default.png, if not, create one, if there is one, check the size or link status, and if it's higher than 1kb, or if we can determine easily if it's a file or link, remove the file, and create a link, if it's already a link, skip it.

This would make updating the loading screens directories easier once you add more apps, and would also make it easier for people with different themes, to switch to a symbolic links based model.

I hope I got my ideas clear, and if you have any questions, let me know! I'll try to explain otherwise!

Thanks a lot for your fast and spot on answers! I really appreciate your help.

(offtopic) Do you have an iphone? If so, are you into theming? Please tell me, you might be interested in seeing what I have done!

This will probably get you close enough. It is similar to the test and remove statement, but specifically checks and removes the .png only if it's a regular file, not a link. Then creates the link if it doesn't exist. I usually write scripts in Kshell, and am not sure what runs on the iPhone; I assume bash and generally Kshell scripts are compatible, but not always.

#!/usr/bin/env ksh
for dir in *
do 
        if [[ -d "$dir" ]] 
        then
                if [[ -f $dir/Default.png ]]            # true if exists and is an ordinary file; dont remove if link
                then
                        rm $dir/Default.png
                fi

                if [[ ! -e $dir/Default.png ]]          # true if it doesnt exist
                then
                        ln -s ../../Default.png $dir/Default.png
                fi
        fi
done

If this isn't exactly what you need, I think you'll be able to modify it. Hope it makes sense.

No, I don't have an iPhone. It's a neat platform, but honestly I want a something that I can put an external SD card into. I want to be able to manage the contents (music etc) on my own -- I don't want to be forced to use iTunes.

1 Like

Hi, this was almost spot on again! Only needed to add "" so the pathnames with space are okay!

The iphone uses standard sh. Also, you can manage your songs without itunes in multiple ways with the iphone, either using mediamonkey, a jailbroken app you can also install and will enable your iphone as a usb drive, and put songs directly in it, from any computer, mac or windows, with no software installed on the pc. Don't even need itunes installed.

And there is also another app on the pc you could use, transcopy, and I think some others too.

Here is my script now:

#!/bin/sh

tmp=/tmp/list.$$
ls -d /var/stash/Themes.* >$tmp 2>/dev/null     # look for existing directories

if [[ -s $tmp ]]     # if tmp file has size, something was found
then
        count=$(wc -l <$tmp)     
        if (( $count > 1 ))
        then
                echo "found more than one Themes directories in /var/stash; please enter path to use:"
                cat $tmp
                read tpath
        else
                read tpath <$tmp                # just get the one path
        fi

        tpath="$tpath/iMatte Loading Screens.theme/Folders"             # build the whole name
else
        echo "could not find a Themes directory in /var/stash [FAIL]"
        exit 1
fi


rm -f $tmp


find /var/mobile/Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        echo "making directory $file_name"    # nice confirmation
        mkdir "$tpath/$file_name"
done

find /Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        echo "making directory $file_name"    # nice confirmation
        mkdir "$tpath/$file_name"
done

cd "$tpath"

for dir in *
do 
        if [[ -d "$dir" ]] 
        then
                if [[ -f "$dir/Default.png" ]]            # true if exists and is an ordinary file; dont remove if link
                then
                        rm "$dir/Default.png"
                fi

                if [[ ! -e "$dir/Default.png" ]]          # true if it doesnt exist
                then
                        ln -s ../../Default.png "$dir/Default.png"
                fi
        fi
done

cd /var/mobile

I tried using for dir in "$tpath/*" or for dir in "$tpath" and it doesnt seem to run that part of the script. That's why I cd to it before, and then it works. I tried to replace one link with a file, and it successfully deleted it and linked instead.

Any other way I can use instead of cd'ing? And this time, no need to write it down for me, but just tell me, if I want to check if folder.app is there, I should nest a similar code you just created, but instead to look for a file, I should look for a dir?

Thanks!

In this case cd'ing to the directory is probably the smart way. If you really wanted to be sure, you could test that the cd command worked before going on:

if ! cd $tpath
then
    echo "unable to switch to $tpath [FAIL]"
    exit 1
fi

Im not sure why putting it into the for loop directly didn't work, but Im tired and might be missing something obvious.

Yes, just add a check for the directory where you need it. Similar to the check for the file, but with -d .

Thanks for the scoop on the iPhone. I had assumed that iTunes was required and the fact that it can appear as a USB disk is wonderful. I might just consider one now!

Glad that you were able to get things working.

If you do get an iphone tho, make sure the one you get is jailbreakable. That's the only downside to having an iphone. You need to get familiar with the jailbreak, and make sure you dont update firmware when a new one comes out.

Once out of jail, it's a wonderful device! I'm not an Apple Fanboy, and the iPhone is the only apple product I own, but it's a really nice device! I'm sure you will like it, specially with your command line skills!

Here is the final product of my script, tell me if I done things right, it now checks for existing directories, and it fixed the problem I had, where even if a file was a link, it was getting removed and recreated.

#!/bin/sh

tmp=/tmp/list.$$
ls -d /var/stash/Themes.* >$tmp 2>/dev/null     # look for existing directories

if [[ -s $tmp ]]     # if tmp file has size, something was found
then
        count=$(wc -l <$tmp)     
        if (( $count > 1 ))
        then
                echo "found more than one Themes directories in /var/stash; please enter path to use:"
                cat $tmp
                read tpath
        else
                read tpath <$tmp                # just get the one path
        fi

        tpath="$tpath/iMatte Loading Screens.theme/Folders"             # build the whole name
else
        echo "could not find a Themes directory in /var/stash [FAIL]"
        exit 1
fi


rm -f $tmp


find /var/mobile/Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        if [[ ! -e "$tpath/$file_name" ]]
        then
        	echo "making directory $file_name"    # nice confirmation
        	mkdir "$tpath/$file_name"
        else
        	echo "there is already a directory named $file_name"
        fi
done

find /Applications/ -name "*.app" -printf "%f\n" | while read file_name
do
        if [[ ! -e "$tpath/$file_name" ]]
        then
		echo "making directory $file_name"    # nice confirmation
        	mkdir "$tpath/$file_name"
        else
        	echo "there is already a directory named $file_name"
        fi
done

if ! cd "$tpath"
then
    echo "unable to switch to "$tpath" [FAIL]"
    exit 1
fi

for dir in *
do 
        if [[ -d "$dir" ]] 
        then
                if [[ -L "$dir/Default.png" ]]            # true if exists and is a symbolic file; remove if not a link.
                then
                        echo "All is good for $dir/Default.png, already a link.  Skipping..."
                elif [[ -e "$dir/Default.png" ]]
                then      
                        echo "Removing $dir/Default.png, it was an ordinary image"
			   rm "$dir/Default.png"
                        echo "Creating a link to ../../Default.png in $dir"
			   ln -s ../../Default.png "$dir/Default.png"
                elif [[ ! -e "$dir/Default.png" ]]          # true if it doesnt exist
                then
                        echo "Creating a link to ../../Default.png in $dir"
			   ln -s ../../Default.png "$dir/Default.png"
                fi

        fi
done

cd /var/mobile

Thank you very much for all your help, you have been most helpful!

PS: If you would like to see the theme I built for the iPhone, go to iMatte | Imatte, Theme, Cydia, Iphone, Complete. You will find many screenshots, video, etc about it! It just went live 2 weeks ago! There is lots of work involved in it! Might even tip in the balance even more for you to get an iphone :slight_smile:

Looks good to me. Glad that you were able to make things work for you. Thanks for the scoop on the iPhone. I'll have a look at the site.