I have a piece of old code that is trying to assign two unicode characters to one unused Unicode character (sorry, I am not using the right terms, but hopefully it gets the issue across). So U17ff is mapped to "ាំ" etc.
Here's the bash script:
for folder in /usr/X11R6/lib/X11/locale/*UTF-8
do
file="$folder/Compose"
if [ -f "$file" ] # is there a compose file?
then
if grep -q "<U17ff>" "$file" # is there Khmer in the file already
then
echo "Warning: $file includes Khmer already!"
else
cp --backup=t --force -v "$file" "$file" # create a backup file
cat Compose >>"$file" # append Khmer
echo "$file Khmer added"
fi
fi
done
The Compose file is this:
# Khmer digraphs
<U17ff> : "ាំ"
<U17fe> : "ោះ"
<U17fd> : "េះ"
<U17fc> : "ុំ"
<U17fb> : "ុះ"
I think the directory isn't right for this code, so the keyboard it is trying to install doesn't work because the unicode character it calls is still blank (I've used the default Khmer keyboard that comes with Ubuntu, and it doesn't work properly, so I am trying to fix it).
Can anyone tell me the directory I should use rather than /usr/X11R6/lib/X11/locale/*UTF-8
For Ubuntu 11.x?
Thanks,
Nathan
Turns out this was a bigger issue than I thought (it is a bug), but there is a way around it:
Type
sudo gedit /etc/environment
Add a line
GTK_IM_MODULE=xim
Save and close.
4.Then in terminal type:
sudo gedit /usr/share/X11/locale/en_US.UTF-8/Compose
Gedit should open, search for Khmer and make sure the following exists (if not, copy and paste it in):
#
# Khmer digraphs
#
<U17ff> : "ាំ"
<U17fe> : "ោះ"
<U17fd> : "េះ"
<U17fc> : "ុំ"
<U17fb> : "ុះ"
Save and reboot.
And everything works fine.
Related
I have successfully changed text in linux using this shell script
vi -e .bash_profile << END
i
PATH=\$PATH:\$HOME/bin:/usr/pgsql-9.4/bin
export PATH
PGDATA=/usr/pgsql-9.4/data
export PGDATA
.
w
q
END
but I have a problem.
If I execute script twice then duplicate in text file.
So, I want to prevent this situation. How Can I fix it?
Well that depends... if the string "PATH=$PATH:$HOME/bin:/usr/pgsql-9.4/bin" can appear at other places in side the file then we could not use it as an indicator that your vi has already done its work. But if the string otherwise does not appear we could wrap the whole thing
grep -q 'PATH=[$]PATH:[$]HOME/bin:/usr/pgsql-9.4/bin' .bash_profile
if [ $? -eq 1 ]
then
# do your vi stuff here
fi
You might replace the if stuff by
test $? -eq 0 && exit 0
if you were not going to do anything after the vi stuff
I'm running a project inside a virtualenv in python. Here's the path to the virtualenv.
~/iss/issp/bin
The problem is when I try to run the activate script with:
source activate
it throws the following error.
:~/iss/issp/bin$ source activate
: command not found
bash: activate: line 4: syntax error near unexpected token `$'{\r''
'ash: activate: line 4: `deactivate () {
Here's the code inside the script:
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
unset pydoc
# reset old environment variables
if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r 2>/dev/null
fi
if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "$1" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/pablo/issp"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "$PYTHONHOME" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
unset PYTHONHOME
fi
if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then
_OLD_VIRTUAL_PS1="$PS1"
if [ "x" != x ] ; then
PS1="$PS1"
else
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
fi
export PS1
fi
alias pydoc="python -m pydoc"
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r 2>/dev/null
fi
The issue is that the activate script has Windows line endings. We can confirm this by running the below command on the command line.
$ file activate
which returns
activate: ASCII text, with CRLF line terminators
CRLF line terminators means windows line endings.
Therefore we need to convert them to Unix line endings so that we can source the file.
We have a few of options
dos2unix activate - (this edits the file in place)
sed -i 's/\r$//' activate (also edits the file in place)
mv activate activate_with_windows_line_endings && (tr -d '\r' < activate_with_windows_line_endings ) > activate here we we just remove any occurrence of \r and the original file is preserved.
Open the file in your favourite text editor. Most will have a way to both show the current line endings of the file (bottom right of image below) and a way to convert them to Unix line endings (In Notepad++ we go to Edit → EOL Conversion → Unix (LF) and then save. Here is a screenshot of how to do it in Notepad++
Finally
Now source activate should work.
Just had the same problem, and decided to do hexdump -C bin/activate to figure out. Turns out my bin/activate file had CR/LF line endings instead of just CR, changing them with (tr -d '\r' < bin/activate) > bin/activatefixed my problem.
I ran into this problem using VS Code and the venv package from python's standard library, since I use bash for my default terminal.
Bash scripts should always use LF instead of CRLF line endings. This is now fixed for the python virtualenv package, but it's still an issue with venv.
As described here, https://bugs.python.org/issue43437, venv copies its activate script template in binary mode when creating new virtual environments. Therefore we only need to convert the original to Unix line endings, using any of Mark's methods above.
The activate script template is located here: <python3_root>/Lib/venv/scripts/common/activate
To fix it in place: sed -i 's/\r$//' activate
As long as that file keeps its LF line endings, new virtual environments created with venv should have viable activation scripts.
Maybe you have an alias in your .bashrc file, that's why deactivate takes like the command, not like a function
instead
deactivate() {
use this
function deactivate() {
This is the script that I used to that will not run, but I am hoping someone can help me figure out what the issue is. I am new to unix
#!/bin/bash
# cat copyit
# copies files
numofargs=$#
listoffiles=
listofcopy=
# Capture all of the arguments passed to the command, store all of the arguments, except
# for the last (the destination)
while [ "$#" -gt 1 ]
do
listoffiles="$listoffiles $1"
shift
done
destination="$1"
# If there are less than two arguments that are entered, or if there are more than two
# arguments, and the last argument is not a valid directory, then display an
# error message
if [ "$numofargs" -lt 2 -o "$numofargs" -gt 2 -a ! -d "$destination" ]
then
echo "Usage: copyit sourcefile destinationfile"
echo" copyit sourcefile(s) directory"
exit 1
fi
# look at each sourcefile
for fromfile in $listoffiles
do
# see if destination file is a directory
if [ -d "$destination" ]
then
destfile="$destination/`basename $fromfile`"
else
destfile="$destination"
fi
# Add the file to the copy list if the file does not already exist, or it
# the user
# says that the file can be overwritten
if [ -f "$destfile" ]
then
echo "$destfile already exist; overwrite it? (yes/no)? \c"
read ans
if [ "$ans" = yes ]
then
listofcopy="$listofcopy $fromfile"
fi
else
listofcopy="$listofcopy $fromfile"
fi
done
# If there is something to copy - copy it
if [ -n "$listofcopy" ]
then
mv $listofcopy $destination
fi
This is what I got and it seems that the script didn't execute all though I did invoke it. I am hoping that someone can help me
[taniamack#localhost ~]$ chmod 555 tryto.txt
[taniamack#localhost ~]$ tryto.txt
bash: tryto.txt: command not found...
[taniamack#localhost ~]$ ./tryto.txt
./tryto.txt: line 7: $'\r': command not found
./tryto.txt: line 11: $'\r': command not found
./tryto.txt: line 16: $'\r': command not found
./tryto.txt: line 43: syntax error near unexpected token `$'do\r''
'/tryto.txt: line 43: `do
Looks like your file contains Windows new line formatting: "\r\n". On Unix, a new line is just "\n". You can use dos2unix (apt-get install dos2unix), to convert your files.
Also have a look at the chmod manual (man chmod).
Most of the time i just use chmod +x ./my_file to give execution rights
I see a few issues. First of all, a mode of 555 means that no one can write to the file. You probably want chmod 755. Second of all, you need to add the current directory to your $PATH variable. In Windows, you also have a %PATH%, but by default the current directory . is always in %PATH%, but in Unix, adding the current directory is highly discouraged because of security concerns. The standard is to put your scripts under the $HOME/bin directory and make that directory the last entry in your $PATH.
First of all: Indent correctly. When you enter a loop or an if statement, indent the lines by four characters (that's the standard). It makes it much easier to read your program.
Another issue is your line endings. It looks like some of the lines have a Windows line ending on them while most others have a Unix/Linux/Mac line ending. Windows ends each line with two characters - Carriage Return and Linefeed while Unix/Linux/Mac end each line with just a Linefeed. The \r is used to represent the Carriage Return character. Use a program editor like vim or gedit. A good program editor will make sure that your line endings are consistent and correct.
I have an automated process that has a number of lines like the following pattern:
sudo cat /some/path/to/a/file >> /some/other/file
I'd like to transform that into a one liner that will only append to /some/other/file if /some/path/to/a/file has not already been added.
Edit
It's clear I need some examples here.
example 1: Updating a .bashrc script for a specific login
example 2: Creating a .screenrc for different logins
example 3: Appending to the end of a /etc/ config file
Some other caveats. The text is going to be added in a block (>>). Consequently, it should be relatively straight forward to see if the entire code block is added or not near the end of a file. I am trying to come up with a simple method for determining whether or not the file has already been appended to the original.
Thanks!
Example python script...
def check_for_appended(new_file, original_file):
""" Checks original_file to see if it has the contents of new_file """
new_lines = reversed(new_file.split("\n"))
original_lines = reversed(original_file.split("\n"))
appended = None
for new_line, orig_line in zip(new_lines, original_lines):
if new_line != orig_line:
appended = False
break
else:
appended = True
return appended
Maybe this will get you started - this GNU awk script:
gawk -v RS='^$' 'NR==FNR{f1=$0;next} {print (index($0,f1) ? "present" : "absent")}' file1 file2
will tell you if the contents of "file1" are present in "file2". It cannot tell you why, e.g. because you previously concatenated file1 onto the end of file2.
Is that all you need? If not update your question to clarify/explain.
Here's a technique to see if a file contains another file
contains_file_in_file() {
local small=$1
local big=$2
awk -v RS="" '{small=$0; getline; exit !index($0, small)}' "$small" "$big"
}
if ! contains_file_in_file /some/path/to/a/file /some/other/file; then
sudo cat /some/path/to/a/file >> /some/other/file
fi
EDIT: Op just told me in the comments that the files he wants to concatenate are bash scripts -- this brings us back to the good ole C preprocessor include guard tactics:
prepend every file with
if [ -z "$__<filename>__" ]; then __<filename>__=1; else
(of course replacing <filename> with the name of the file) and at the end
fi
this way, you surround the script in each file with a test for something that's only true once.
Does this work for you?
sudo (set -o noclobber; date > /tmp/testfile)
noclobber prevents overwriting an existing file.
I think it doesn't, since you wrote you want to append something but this technique might help.
When the appending all occurs in one script, then use a flag:
if [ -z "${appended_the_file}" ]; then
cat /some/path/to/a/file >> /some/other/file
appended_the_file="Yes I have done it except for permission/right issues"
fi
I would continue into writing a function appendOnce { .. }, with the content above. If you really want an ugly oneliner (ugly: pain for the eye and colleague):
test -z "${ugly}" && cat /some/path/to/a/file >> /some/other/file && ugly="dirt"
Combining this with sudo:
test -z "${ugly}" && sudo "cat /some/path/to/a/file >> /some/other/file" && ugly="dirt"
It appears that what you want is a collection of script segments which can be run as a unit. Your approach -- making them into a single file -- is hard to maintain and subject to a variety of race conditions, making its implementation tricky.
A far simpler approach, similar to that used by most modern Linux distributions, is to create a directory of scripts, say ~/.bashrc.d and keep each chunk as an individual file in that directory.
The driver (which replaces the concatenation of all those files) just runs the scripts in the directory one at a time:
if [[ -d ~/.bashrc.d ]]; then
for f in ~/.bashrc.d/*; do
if [[ -f "$f" ]]; then
source "$f"
fi
done
fi
To add a file from a skeleton directory, just make a new symlink.
add_fragment() {
if [[ -f "$FRAGMENT_SKELETON/$1" ]]; then
# The following will silently fail if the symlink already
# exists. If you wanted to report that, you could add || echo...
ln -s "$FRAGMENT_SKELETON/$1" "~/.bashrc.d/$1" 2>>/dev/null
else
echo "Not a valid fragment name: '$1'"
exit 1
fi
}
Of course, it is possible to effectively index the files by contents rather than by name. But in most cases, indexing by name will work better, because it is robust against editing the script fragment. If you used content checks (md5sum, for example), you would run the risk of having an old and a new version of the same fragment, both active, and without an obvious way to remove the old one.
But it should be straight-forward to adapt the above structure to whatever requirements and constraints you might have.
For example, if symlinks are not possible (because the skeleton and the instance do not share a filesystem, for example), then you can copy the files instead. You might want to avoid the copy if the file is already present and has the same content, but that's just for efficiency and it might not be very important if the script fragments are small. Alternatively, you could use rsync to keep the skeleton and the instance(s) in sync with each other; that would be a very reliable and low-maintenance solution.
HI,
I have cygwin installed in my Windows system.
I have written two function in my profile file so that every time I open vi/vim, it will open with gvim.
But with this one of the issue, the windows path and Cygwin path. I tried with Cygpath as below:
function vi ()
{
win_file_path=$(cygpath -w $*)
gvim "$win_file_path" &
}
Bu with this, when ever I open a file like this: "vi /etc/exports +5", it will result in error. So let me know if any of you have any solution.
You can treat the file arguments only:
function vi ()
{
local -a viargs
local a
while [[ $# -gt 0 ]]
do
a="$1"
if [ -e "$a" ]; then a="$(cygpath -w "$a")"; fi
viargs[${#viargs[#]}]="$a"
shift
done
gvim "${viargs[#]}" &
}
Instead of being 'smart' about existing files like this, feel free to simplify to treat just the first argument :)
In recent bash versions you can replace the ugly line
viargs[${#viargs[#]}]="$a"
with
viargs+=( "$a" )
cyg-wrapper has been written for this sole purpose.
NB: See also the related wikia page.