Linux 'cp' copies symlink instead of target file

4,377

Solution 1

Try this,

let the destination be /tmp/

If you want to copy the target file but not the symlink, :

readlink -ne base.txt | xargs -0 cp -t /tmp/

Solution 2

Copying to a directory creates a new file with the same name as the source file in the target directory, if a new file name is not given. So the following commands will give the same output:

> cp base_v21.txt /targetdir
> cp base_v21.txt /targetdir/base_v21.txt

These create a new file called "base_v21.txt" with the contents of the file in the source directory. In this case, these are the contents of "base_v001.txt" because of the symbolic link. Essentially, you are doing the following:

> cat base_v21.txt >> /targetdir/base_v21.txt

Thus it is to be expected that the following commands give the same result after copying:

> cat base_v21.txt
> cat base_v001.txt
> cat /targetdir/base_v21.txt

You can see that this occurs with either a hard link or symbolic link in the following examples:

> touch base_v001.txt
> ln -s base_v001.txt base_v21.txt #create soft link
> cat "test" >> base_v001.txt
> mkdir dir
> cd dir
> cp ../base_v21.txt .
> ls
base_v21.txt

>cat base_v21.txt
test

> ln base_v001.txt base_v21.txt #create hard link
> cat "test" >> base_v001.txt
> mkdir dir
> cd dir
> cp ../base_v21.txt .
> ls
base_v21.txt

>cat base_v21.txt
test
Share:
4,377

Related videos on Youtube

Alex Harvey
Author by

Alex Harvey

Updated on September 18, 2022

Comments

  • Alex Harvey
    Alex Harvey almost 2 years

    This is probably a beginner question but I'm really pulling my hair out.

    I have a very simple Python script "foo":

    #!/usr/bin/env python
    
    class Foo():
      def __init__(self):
        self.do_something()
    
      def do_something(self):
        print "foo"
    
    def main():
      Foo()
    
    if __name__ == '__main__':
      main()
    

    Script works fine:

    $ python foo.py 
    foo
    

    I want to test the function "do_something" in unittest and I have this code:

    #!/usr/bin/env python
    
    import unittest
    import foo
    from foo import *
    
    class TestFoo(unittest.TestCase):
      def test_foo(self):
        Foo()
    
    def main():
      unittest.main()
    
    if __name__ == "__main__":
      main()
    

    If I run the tests, however, I get:

    $ python pyunit/foo.py
    E
    ======================================================================
    ERROR: test_foo (__main__.TestFoo)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "pyunit/foo.py", line 9, in test_foo
        Foo()
    NameError: global name 'Foo' is not defined
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    
    FAILED (errors=1)
    

    My project structure:

    $ tree 
    .
    ├── foo.py
    └── pyunit
        └── foo.py
    

    I have been playing around with inspect, dir(), the Python debugger etc but I'm getting nowhere.

    Although import foo and from foo import * both execute fine, and I see the function main imported from that file, the class itself Foo doesn't seem to be imported.

    My objective, ultimately, is to then write unit tests for the functions in the class Foo.

    What am I doing wrong?

    • Chen A.
      Chen A. almost 7 years
      Have you tried using one import statement? from foo import *, then you don't need the import foo statement above
    • Francis Colas
      Francis Colas almost 7 years
      Could it be that the foo module you import is the test file instead of the original? Try renaming your pyunit/foo.py into pyunit/test_foo.py and see what happens.
    • Alex Harvey
      Alex Harvey almost 7 years
      No, I tried both of these suggestions and I have the same result.
    • schily
      schily almost 6 years
      You shuold edit your question to make it understandable. Check the "base" names....
    • A.B
      A.B almost 6 years
      giving the output of ls -l instead of only ls would make things more clear for all the answerers
    • ilkkachu
      ilkkachu almost 6 years
      cp base_v001.txt /targetdir produces /targetdir/base_v21.txt? Are you absolutely sure? There's no way for the system to know what symlinks are pointing to that file. I would understand this if you used the symlink as the copy source and got the name from the symlink destination instead, or something like that.
    • ETD
      ETD almost 6 years
      @ilkkachu Yes, I understand it's a odd result. I've searched the web for a similar occurrence, but so far have not seen any. It forced me to make an account and post this question.
  • Alex Harvey
    Alex Harvey almost 7 years
    No, I'm afraid that doesn't work. That leads to an error ImportError: No module named pyunit.
  • Chen A.
    Chen A. almost 7 years
    Add to your pyunit folder a new empty file named __init__.py, this will make python address the folder as a package
  • Alex Harvey
    Alex Harvey almost 7 years
    Nope. no difference.
  • Chen A.
    Chen A. almost 7 years
    Can you update the folder tree after changing the file names?
  • Alex Harvey
    Alex Harvey almost 7 years
    Ok, I updated the question with this info since seems there's no way to paste it here.
  • Chen A.
    Chen A. almost 7 years
    Ok so you are running python pyunit/test_foo.py now instead of foo.py right? then your import needs to be changed to: import <top_level_dir> import foo where top level dir is where foo.py resides
  • Alex Harvey
    Alex Harvey almost 7 years
    Ok I was able to get the file using: import sys ; sys.path.insert(0, '.') ; from foo import *. You're on the right track. Your answer, as it stands, is not correct. Importing from pyunit doesn't make much sense to me, and it certainly doesn't work. Would you like to fix it?
  • Chen A.
    Chen A. almost 7 years
    @AlexHarvey you had multiple issues in one question ;) I updated my answer accordignly
  • Alex Harvey
    Alex Harvey almost 7 years
    I believe I only had one issue, which was that as Francis Colas suggested, I was accidentally importing from the foo.py file inside my tests directory (i.e. inside my pyunit directory). By trying to turn the pyunit directory into a module, which is what you seem to be suggesting, I would still be importing from the wrong place, and in any case, as I said, the code you provided simply doesn't work. So I can't mark the answer as correct unless you fix that.
  • Chen A.
    Chen A. almost 7 years
    @AlexHarvey done, I removed what's not relevant and summarized it
  • Eminent
    Eminent almost 6 years
    It seems the OP describes a situation in which running the command cp base_v001.txt /targetdir returns with the file (symbolic link) named /targetdir/base_v21.txt. You don't find that strange?
  • ilkkachu
    ilkkachu almost 6 years
    Wait, I read the file names wrong. The way it's actually written is so weird I must have mentally blocked the idea, or something... Sorry.