How can the same move command behave differently depending on the context? - bash

This should be trivial really, I have a script that compile an app then bundle it into a dmg.
The steps are:
make
mv app.app/ installer/artifacts/
createDMG
The problem is this runs within a CI system and it fail because it can't find the app.app in the artifacts folder. Indeed if I look at what's inside this folder I can only see a Content folder which is supposed to be app.app's child folder. Now I don't think that the command to move the app.pp folder is wrong because when I run all those 3 steps it works just fine...
I'm a bit confused now, how can 2 move command can have 2 different behaviors ?

If the folder installer/artifacts/ does not exist, move will rename app.app/ to installer/artifacts/
You could do the following instead:
make
mkdir -p installer/artifacts/
mv app.app installer/artifacts/
createDMG

Related

having trouble with cd and getting back to a directory

For school, I have to switch between my top level directory which is git-basics-lab-online-web-sp-000 back to the sub directory I made which is called my-repository.
I was switching back and forth no problem using {cd} but when I tried to switch back to my-repository using
cd my-repository
my terminal is now saying
bash: cd: my-repository: No such file or directory
what did I do wrong?! How come it worked before but now it's giving me this message?
Perhaps we are missing more information. That is, if you moved correctly from one directory to another, there is no reason why it should disappear just like that.
Besides cd, there are other commands that will help you to know which directory you are in, and where you can go. I summarize them below:
Show the full path to the current directory:
pwd
List files and folders (except hidden ones):
ls
Enter the dir directory (assuming it exists where we are):
cd dir
Exit dir (see edit):
cd ..
Obviously each command has a number of options that increase its functionality. You can always access them with the man command (for example, man cd will show you the cd command help).
That is, once the terminal showed you the error you mention, you can run ls to verify, for example, if you typed the folder name wrong. Then you can also try pwd to confirm that you are where you think you are. And finally you can move with cd to where you think you are.
EDIT: As suggested by Roadowl, cd - and cd .. are not strictly the same thing (in the example I assume we go one directory at a time).
I will try to illustrate this with an example to show the difference.
Suppose we have the dirc folder inside dirb and this, in turn, inside dira ( dira/dirb/dirc ). Let us also suppose that we are in dira. To enter directly to dirc we would have to execute cd dirb/dirc. And this is where the difference is illustrated:
If we run cd .. we are going to be positioned in dirb.
If we run cd - we will go back to the dira directory we were in before running the command.
This error message simply means that the directory/file you specified could not be found at your current location. If you look to the left of where you are typing, your current directory should be displayed, something like /you/are/here/ >
You can type cd .. to navigate up one level (towards the root directory).
If you are sure the directory exists you are trying to cd into, then you probably just aren't currently in the right location, and you need to either cd .. or cd somewhereelse until you get there.

purpose of chdir with a single dot (cd .)

This might appear a noob question.
While working in bash, if we run cd ., it stays in the current folder.
I understand the functionality, however, I am not able to understand the rationale of this functionality?
What would be some practical ways to use this?
The primary use case I've seen for cd . is to test whether your file handle on the current directory is still valid.
If you're on a directory from a network share -- NFS, or the like -- it can be possible for directories to be remotely deleted, but for the local client to still believe they're accessible and in use.
cd . is a way to trigger an error if your handle on the current working directory is no longer valid.
This is the only "practical" case that came to my mind
$ cd .
cd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
when your process has a current working directory referencing a directory that has been removed by another process.
That command has no functionality. But in a POSIX-compliant environment, if you add a -P option, then it has functionality: it resolves symlinks. So for example on a Mac, if you cd to a path with a symlink:
cd /System/Library/Frameworks/AppKit.framework/Versions/Current
...then do cd -P . ... you will point to:
/System/Library/Frameworks/AppKit.framework/Versions/C
. is a special file that represents the current directory.
There are plenty of things which make use of directories and it is sometimes useful to refer to the current directory.
Changing the directory to the current directory is not one of those.
A simple example where cd . fails:
mkdir my_error
cd my_error
rm -rf ../my_error
cd .
When the rm is embedded in a difficult script or can be done by some other cleanup process, is can be an useful check.
I use a build script which removes and recreates a directory.
The old directory disappears and new appears with new inode.
If, in one of my shells my $PWD is that reappeared directory and I notice
it became unusable (and I know it was recreated), I just
$ cd .
to get the (new) directory useable again and can continue my work there.

Xcode appears to be modifying paths inside bash scripts during run script build phase

I have a simple script that looks like this:
#!/bin/sh
set -eux
install_folder="${HOME}/Library/MobileDevice/Provisioning Profiles"
mkdir -p "${install_folder}"
if [[ $? != 0 ]]; then
echo "Unable to create destination directory: ${install_folder}"
exit 1
fi
If I run this script from the command line by doing ./my_script.sh everything works as expected. Things go wrong though when I call from Xcode as part of a run script build phase. I currently call it by having "${SRCROOT}/path/to/my_script.sh" in the run script build phase, but the same issue occurs even if I copy and paste the code above in directly.
So what's the issue? Well, it seems Xcode is causing the wrong folder to be created. When I run from the command line, I get a folder named Provisioning Profiles inside ~/Library/MobileDevice/ as expected. When I run from Xcode, the folder is named Provisioning\ Profiles (that \ is literally part of the name).
But it gets weirder. If I change the mkdir line to mkdir -p $install_folder then I'd expect to get a folder called Provisioning inside the MobileDevice folder and a folder called Profiles wherever I ran the command. That's what happens when I run from the command line. If I run from Xcode however, I get a folder Profiles inside MobileDevice but I also get a folder called Provisioning\ Profiles.
I cannot explain this behavior at all. It seems totally counter to everything I (thought) knew about shell scripts.
How is Xcode influencing this? How do I make it stop?
The trick, as always, was realising that there was more to this than I had considered. Xcode wasn't just running this script in the phase, it was doing it with a list of output files set. It was then creating the path for those after it ran the script. The script was behaving exactly as it should have, it was just the extra stuff which made it appear to be broken.
Lesson learned: Xcode will create a folder for output files if it doesn't exist.

IBM Integration bus mqsicreatebar with references

I'm bit confused with using mqsicreatebar in my environment. I have, for example, following file structure:
root
|--Libraries
| \--Library1
\--Apps
\--App1
\--.project
And App1 is referencing Library1.
I want to run mqsicreatebar such that it will contain App1 with included Library1. I try to run next command in root/Apps folder:
mqsicreatebar -data ./ -b newbarfile.bar -cleanBuild -deployAsSource -a App1 -trace
I get error "Referenced project Library1 is not found on file system". What should I do to create BAR with this file structure?
That "data" parameter tells the mqsicreatebar command where to find an eclipse workspace (Integration Toolkit workspace) that in turn tells the mqsicreatebar command where the project files and other files it needs for the build are.
If you don't have a workspace there already, the command will create one on the fly for you, but only for the current directory and its subdirectories. I do not know how deep this goes. I know it looks at least one subdirectory down for project files (though your comments imply it does not look down two subdirectories).
Alternatively, (and I understand this is not desired, but it's an option, similar to the one you already posted) you could give up on your folder organization and put your library and app subfolders in the same root folder. So you have:
root
|--Library_1
|--Library_2
|--App_1
|--App_2
This is what I have set up in my Bamboo project and the build commands work (even with no workspace files before running the command, as long as I point the data parameter at this root directory).
The only way I've found by myself is copying necessary artifacts to current directory before running mqsicreatebar and deleting them after build completion:
cd /root/Apps/
cp -R ../Libraries/Library1/ ./
mqsicreatebar -data ./ -b newbarfile.bar -cleanBuild -deployAsSource -a App1 -trace
rm -r Library1/

Add files to an Xcode project from a script?

Right now I'm using a few scripts to generate files that I'm including as resources in Xcode. The thing is I'm running the script, then deleting from the project, then adding back into the project. There must be a way to automate this last step, so that the script can generate the files and automatically add them into the xcode project for me.
I'm using bash but any language examples would help.
Thanks,
Andrew
I had a similar need as Andrew. I needed to be able to include resources from a script without knowing those resources ahead of time. Here's the solutions I came up with:
Add a new Run Script build phase after “Copy Bundle Resource” that contains the following command:
find -L ${SRCROOT}/SomeDerivedResources \
-type f -not -name ".*" \
-not -name "`basename ${INFOPLIST_FILE}`" \
| xargs -t -I {} \
cp {} ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/
Looks scary, but let’s break it down:
find -L ${SRCROOT}/SomeDerivedResources
This crawls the directory SomeDerivedResources in our source root (-L tells it to follow symbolic links)
-type f
Only include regular files
-not -name ".*"
Ignore files starting with a dot
-not -name "`basename ${INFOPLIST_FILE}`"
In my case, my Info plists live in my SomeDerivedResources directory so we need to exclude that file from being copied to our product
| xargs -t -I {}
Pipe the results of find into xargs with -t (echo resulting commands to stderr so they show up in our build log), -I (run the command once for each input file) and use {} as our argument placeholder
cp {} ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/
Lastly, copy each found file (denoted by {}) to our product’s resource directory.
I realized when typing this that using an rsync setup instead of cp could prevent us from copying resources each time you build. If your resources are very large it might be worth looking in to.
(Also, a folder reference wouldn’t work for my need for a few reasons. One, my icons are in my DerivedResources directory and having them in a subdirectory in the bundle seems not to work. Also, I ideally wanted to be able to use [UIImage imageNamed:#"MyAwesomeHappyImage.png"] and -pathForResource:ofType: (and some of my files are nested further inside my DerivedResources directory). If your needs don’t contain those restraints, I highly suggest you go the folder reference route.)
This can be done by adding a new build phase to your application.
In your Xcode project browser, find the target for your application, and expand it to show all of the build phases.
Add a new "run script" build phase to your target. The easiest way is to right-click on the target and choose "Add/New Build Phase/New Run Script Build Phase"
Adding the new build phase should bring up an inspector window. In this window, you can enter the entire shell script, or simply a command line to run the script.
Here's the gold: At the bottom of the inspector window you can specify input files and output files. Specifying input files sets up dependencies automatically (the shell script will only be executed if some of the input files have been modified). Specifying output files automatically propagates the dependencies to those files. When your shell script is run, Xcode knows that it needs to deal with those files that the shell script has modified.
Be sure to drag your new build phase up to the top of the list of phases as shown in the screenshot below. The order will be important if you need those resource files to be included in the bundle.
Save, build, commit to the repository, ask for a raise, get some fresh air and have a nice day! :)
For those with large number of files, to avoid having to recopy (or recheck) each file, as suggested by #Ben Cochran (thanks a lot for the great script), this is how to do it with rsync:
Basically, the files just need to be copied into the main bundle
In that case just add a folder reference to the project (Create a folder in your project folder and then drag it into your projects "Resources" group (in the "Files & Groups" list; then in the sheet that appears select the "Create Folder References for any added Folder" radio button) and Xcode will copy the folder and all of its contents into the target bundle at build time.
Just an additional note: If you use this method to add image subfolders you'll have to prefix the image name with the subfolder name to use '[UIImage imageNamed:]'. For example if you have an image named "Rendezvous.png" in a subfolder named "MyImages":
`
// this won't work
UIImage * image = [UIImage imageNamed:#"Rendezvous"];
if (image) {
NSLog(#"Found Rendezvous!");
} else {
NSLog(#"Didn't find Rendezvous.");
}
// but this will!
image = [UIImage imageNamed:#"MyImages/Rendezvous"];
if (image) {
NSLog(#"Found MyImages/Rendezvous!");
} else {
NSLog(#"Didn't find MyImages/Rendezvous.");
}
`
If you already have the files somewhere on your system, relative to your source root, you can always add a "Copy Files" phase. This will allow you to specify a directory where your resources should be copied from.
You can combine this with the Build Script phase answer provided to you already. For instance, run a script to check out your assets from Subversion into a subdirectory of your project, and then follow that up with a Copy Files phase that copies from "$(SRCROOT)/Assets".
I know it's a bit late, but I just came across this article explaining how to do something that sounds like what you're looking for.
I found myself with a similar situation using Ionic Capacitor. What I was expecting was to include files on the "Copy Bundle Resources" bundle phase. What I found is that Ionic already packs you some inclusions and if you slip your files along this folders you get it included as well.
Do you see the App folder inclusion? It our entry point.
To include on it I add a script that do something like this:
cp -Rf ./includes/yourfolder/ ./ios/App/App/
I managed to solve the issue
"Code object is not signed at all"
that can be encountered during build upload to iTunes Connect in this way:
I didnot include the script to Bundle resources.
So the script (in this case Python file) is executed during build, (it does what it has to do) but it is not included in the bundle of the app.
How to do?
Open Build Phases, go to Copy Bundle Resources section, select the file and remove it with (-).

Resources