How to rewrite file to file using bash? - bash

I create builds using AppCenter.ms. But My project has many CustomAndroidManifest.xml files. It places on UserApp/UserApp.Android/Properties/
AppCenter automatically increments version code. But AppCenter changes it in AndroidManifest.xml.
Task: I need to rewrite CustomAndroidManifest.xml to AndroidManifest.xml before AppCenter will change build number.
Why I have many CustomAndroidManifests... because My App has many Configurations.
I've created appcenter-post-clone.sh file and put it in Droid folder. Please look at the my script:
#!/usr/bin/env bash
if [ "$APPCENTER_XAMARIN_CONFIGURATION" == "Conf1" ];
then
cp -R $APPCENTER_SOURCE_DIRECTORY/UserApp/UserApp.Android/Properties/Conf1AndroidManifest.xml/. $APPCENTER_SOURCE_DIRECTORY/UserApp/UserApp.Android/Properties/AndroidManifest.xml/
if [ "$APPCENTER_XAMARIN_CONFIGURATION" == "Conf2" ];
then
cp -R $APPCENTER_SOURCE_DIRECTORY/UserApp/UserApp.Android/Properties/Conf2AndroidManifest.xml/. $APPCENTER_SOURCE_DIRECTORY/UserApp/UserApp.Android/Properties/AndroidManifest.xml/
fi
Main Idea is change first file to second. Thank you.
EDIT! Problem is that CustomAndroidManifest.xml dos not rewrite to AndroidManifest.xml.
Question: How can I rewrite one file to second using bash?

Related

How can I refer to the first file in an .xcfilelist within an Xcode build script?

How can I refer to the first file in an .xcfilelist within an Xcode build script?
If I list the files separately (instead of using an .xcfilelist) then I can use SCRIPT_OUTPUT_FILE_0 of course. However if I use a .xcfilelist instead, then how can I reference that first output file?
The only reason we want to use the .xcfilelist in the first place is so Xcode doesn't re-run the script and rebuild the module every single time we run a compile. However that's exactly what it's doing... it seems to be ignoring what's specified in the output file list's .xcfilelist and always regenerating those files and then recompiling them even when nothing has changed.
Seems like an Xcode bug but figured maybe we could compare the modification times at the beginning of the script by referencing the first file in the file list, but I cannot seem to find a way to do that.
If you want to iterate over all lines in all xcfilelists then this simplistic script can do it:
for index in $(seq $SCRIPT_INPUT_FILE_LIST_COUNT); do
# 1 => `SCRIPT_INPUT_FILE_LIST_0`
filelist=SCRIPT_INPUT_FILE_LIST_$((index-1))
# `SCRIPT_INPUT_FILE_LIST_0` => value in $SCRIPT_INPUT_FILE_LIST_0
filelist_path=${!filelist}
while read -r file_path; do
echo "${file_path}"
done <$filelist_path
done
It will dynamically construct the SCRIPT_INPUT_FILE_LIST_0, SCRIPT_INPUT_FILE_LIST_1, etc. values and access them from the environment vars passed to the script by Xcode.

7zip - don't add to existing archive, create new archive only

I'm creating a bash script that includes a function to compress a file to a new archive.
Basic example:
archive_path="/foo.7z"
target="/bar.txt"
7z a $archive_path $target
The problem I have is that I only ever want to create a new archive. If there are any existing archives at /foo.7z then bar.txt should not be added to it. Instead, either prompt the user to create a new name for the archive or just append a number on the end and create a new archive (e.g. /foo-1.7z).
I can't find anything in the documentation, on SO or a general internet search that explains how to do this natively with 7zip, which seems strange as I imagine it would be a very common requirement amongst users.
The only solution I can think of is to do this myself manually, something along the lines of:
archive_path="/foo.7z"
target="/bar.txt"
while [ -f $archive_path ]; do
read -p "'$archive_path' already exists. Enter new path for archive: " archive_path
done
7z a $archive_path $target
Is there any other way to do it natively with 7zip or do I need to handle this myself?
There doesn't seem to be any way of doing this with just 7z. While there is a "new archive" switch for the update flag, it will create both the new name and old one, plus you run into the problem of what happens when the new one exists as well. The best option is to do what you've done, or alternatively, something like this could work
arc='archive.7z'
new_arc=${arc}
target='file.txt'
while [[ -f ${new_arc} ]]; do
((i++))
new_arc=${arc%.*}${i}.${arc#*.}
done
7z a "${new_arc}" "${target}"
Which will rename the archive filename with an integer added before the extension (+1 each loop) until no file is found by that name. So you'll get archive.7z archive1.7z archive2.7z archive3.7z and so forth.

xcode 5 localize storyboard with script delete *.strings file?

sorry to make another bother.
I'm implement an app, with localization of English and Japanese in xcode 5, using the script file created by André Pinto, based on SIngle Storyboard for multiple languages. Well, before upgrade to xcode 5 (xcode 4.6, I mean), things work properly. But since xcode 5, this error occurs when run the script file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.ibtool.errors</key>
<array>
<dict>
<key>description</key>
<string>Interface Builder could not open the document "xx.storyboard" because it does not exist.</string>
</dict>
</array>
</dict>
</plist>
Iconv: ./xx/Base.lproj/xx.strings.new: No such file or directory
Rm: ./xx/Base.lproj/xx.strings.new: No such file or directory
Merging xx.strings changes for en.lproj...
Merging xx.strings changes for ja.lproj...
Command /bin/sh emitted errors but did not return a nonzero exit code to indicate failure
In the storyboard, there are 2 sub-files: xx.storyboard(Base) and xx.storyboard(Japanese)
In the first build, no error occur. Everything went fine. App localize so good.
In the second build, I made somechange in storyboard (add some new feature), then error occur. Also, the xx.storyboard(Japanese) become blank, and this is weird. I put lots of effort translate those things, and now I have to do it again...
I think there's some problem with the script, the strings.new and strings.old...
Here's the script:
#!/bin/sh
# Update storyboard string files
#
# by 2013 André Pinto andredsp#gmail.com
# based on http://forums.macrumors.com/showthread.php?t=1467446
storyboardExt=".storyboard"
stringsExt=".strings"
newStringsExt=".strings.new"
oldStringsExt=".strings.old"
localeDirExt=".lproj"
baselprojName="Base.lproj"
# Find Base internationalization folders
find . -name "$baselprojName" | while read baselprojPath
do
# Get Base project dir
baselprojDir=$(dirname "$baselprojPath")
# Find storyboard file full path inside base project folder
find "$baselprojPath" -name "*$storyboardExt" | while read storyboardPath
do
# Get Base strings file full path
baseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$stringsExt/")
# Get storyboard file name and folder
storyboardFile=$(basename "$storyboardPath")
storyboardDir=$(dirname "$storyboardPath")
# Create strings file only when storyboard file newer
newer=$(find "$storyboardPath" -prune -newer "$baseStringsPath")
[ -f "$baseStringsPath" -a -z "$newer" ] && {
echo "$storyboardFile file not modified."
continue
}
# Get New Base strings file full path and strings file name
newBaseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$newStringsExt/")
stringsFile=$(basename "$baseStringsPath")
echo "Creating default $stringsFile for $storyboardFile..."
ibtool --export-strings-file "$newBaseStringsPath" "$storyboardPath"
iconv -f UTF-16 -t UTF-8 "$newBaseStringsPath" > "$baseStringsPath"
rm "$newBaseStringsPath"
# Get all locale strings folder with same parent as Base
ls -d "$baselprojDir/"*"$localeDirExt" | while read localeStringsDir
do
# Skip Base strings folder
[ "$localeStringsDir" = "$storyboardDir" ] && continue
localeDir=$(basename "$localeStringsDir")
localeStringsPath="$localeStringsDir/$stringsFile"
# Just copy base strings file on first time
if [ ! -e "$localeStringsPath" ]; then
echo "Copying default $stringsFile for $localeDir..."
cp "$baseStringsPath" "$localeStringsPath"
else
echo "Merging $stringsFile changes for $localeDir..."
oldLocaleStringsPath=$(echo "$localeStringsPath" | sed "s/$stringsExt/$oldStringsExt/")
cp "$localeStringsPath" "$oldLocaleStringsPath"
# Merge baseStringsPath to localeStringsPath
awk '
NR == FNR && /^\/\*/ {
x=$0
getline
a[x]=$0
next
}
/^\/\*/ {
x=$0
print
getline
$0=a[x]?a[x]:$0
printf $0"\n\n"
}' "$oldLocaleStringsPath" "$baseStringsPath" > "$localeStringsPath"
rm "$oldLocaleStringsPath"
fi
done
done
done
Localizable.strings and InfoPlist.strings are still good.
Anyone has experience with this kind of things help me please... Is that something with xcode, or script file or xx.strings file? I don't get it...
I may ask it directly the script's creator, but I think post the question here will be better. I'm a SO lover :)
I was using same script as you, and had the same issues as you. Then I found these articles from AppliedIS, detailing their process of I18n and L10n. They used an updated version of this script that seems to be slightly more robust.
They also have a script for extracting keys from NSLocalizedString statements and generate Localizable.strings for every locale as well. This script uses the comment as the value when generating the new entries, which is quite clever.
I have switched to these now, and it seems faster (that might be just me; ooh, new == faster), has more output (nice for debugging) and it also works without the Run script only when installing.
Check it out! (I'm not associated with them in any way, just a happy user)
I think this is the solution:
go to xx.xcodeproj-> Target-> Build phases-> Run Script-> Tick on "Run script only when installing"
I don't know how, why but this seems to solve the problem... I think because the script run when install on ios simulator, so when I build, it can't find the xx.storyboard...
Any other answers are still welcome. I still can't satisfy with this one, because there's no guarantee with this solution.
I believe localization only occurs during the install of an app. Therefore your workaround has every reason to work since the script deals with localizing resources. Please note that many things in localization have changed and it would be worthwhile to review the linked internationalization guide located on the Apple developer website. The link contains specific videos and programming topics that provider further explanations. Some things worth considering is that you should use Autolayout if you only plan on using a single view controller. This will ensure your translations size correctly in each language.

How to output a list of files on bash command line

I am using handlebars.js to render client-side templates (using Jade on the node.js server-side) for our single-page app.
I want to precompile the handlebars templates on the server side and bundle them up as one JS file to send to the client.
Currently, I use handlebars to compile templates like so:
$ handlebars template1.handlebars template2.handlebars -f precompiled_templates.js
I'd like to write a bash script that can read all the *.handlebars files in a directory and then run them through the handlebars compiler. So, if I had a directory like so:
templates/
temp1.handlebars
temp2.handlebars
temp3.handlebars
temp4.handlebars
Running my bash script (or, one line command) in the templates directory would essentially run the following handlebars command:
$ handlebars temp1.handlebars temp2.handlebars temp3.handlebars temp4.handlebars -f precompiled_templates.js
Does anyone know how I could write a bash script to get all the handlebars files in a directory onto the command line like above?
It looks like you want something similar to
handlebars templates/*.handlebars -f precompiled_templates.js
except you would end up with 'templates' prefixed to each file. My preferred approach requires two lines:
files=( templates/*.handlebars )
handlebars "${files[#]#templates/}" -f precompiled_templates.js.
The first line puts all the desired files in an array. In the second line, we expand the contents of the array, but stripping the "templates/" prefix from each element in the resulting expansion.
In the templates directory do:
handlebars `find -name *.handlebars` -f precompiled_templates.js
The back-ticks means it will execute that command then return the result, so you in effect you run handlebars on each file it returns. As written above find will look in current and subdirectories for the files so make sure you run it from the right place.
In Bash, lists can be create with string within double quote :
FILES="/etc/hosts /etc/passwd"
for file in $FILES; do cat $file ; done
<cat all files>
You can also use find and exec commands.
man [find|exec] for more informations

How to include file as resource in Xcode programmatically during build?

I have a file that is created by a script that is run during a build phase. Consequently, the file does not exist until build time.
How can I add the file to the app/project so that my code can access it at run time?
I know what the filename will be.
Normally, if I created the file by hand, I would just drag/drop it into Xcode, and I can instantly access it by using the filename in code. Since I am generating the file during build, I want to know how I can add it to my project.
EDIT: The file that I am adding is an Image file, that is created by a script during a build phase. I want to be able to access this file at runtime in my product.
I ended up using build references.
You could create the file and add it to the project and then during the build phase, your script could replace the existing file with the generated one....
The other option is to try manipulating the project file itself but that's quite complicated. Here are some resources on the subject...
You can copy the generated file to the build output using a script like this one I use to copy a plist with values maintained outside version control, as anything copied to "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/" is available using NSBundle APIs.
SECRETS="${SRCROOT}/../../secrets/Secrets.plist"
APP="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/Secrets.plist"
if [ -f "$SECRETS" ]; then
cp -f "$SECRETS" "$APP"
echo "copied Secrets.plist: $APP"
else
echo "Secrets.plist not found at $SECRETS, all secrets will be 'MISSING'"
fi
For instance, that plist of secrets is defined as the Decodable struct SecretsFile and loaded with
private static var file: SecretsFile? = {
guard let url = Bundle.main.url(forResource: "Secrets", withExtension: "plist"),
let data = try? Data(contentsOf: url) else { return nil }
return try? PropertyListDecoder().decode(SecretsFile.self, from: data)
}()

Resources